OpenCores
URL https://opencores.org/ocsvn/altor32/altor32/trunk

Subversion Repositories altor32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /altor32/trunk
    from Rev 26 to Rev 27
    Reverse comparison

Rev 26 → Rev 27

/rtl/soc/dmem_mux3.v
0,0 → 1,199
 
//-----------------------------------------------------------------
// Module:
//-----------------------------------------------------------------
module dmem_mux3
(
// Outputs
out0_addr_o,
out0_data_o,
out0_data_i,
out0_wr_o,
out0_rd_o,
out0_burst_o,
out0_ack_i,
out0_accept_i,
out1_addr_o,
out1_data_o,
out1_data_i,
out1_wr_o,
out1_rd_o,
out1_burst_o,
out1_ack_i,
out1_accept_i,
out2_addr_o,
out2_data_o,
out2_data_i,
out2_wr_o,
out2_rd_o,
out2_burst_o,
out2_ack_i,
out2_accept_i,
 
// Input
mem_addr_i,
mem_data_i,
mem_data_o,
mem_burst_i,
mem_wr_i,
mem_rd_i,
mem_ack_o,
mem_accept_o
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter ADDR_MUX_START = 28;
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input [31:0] mem_addr_i /*verilator public*/;
input [31:0] mem_data_i /*verilator public*/;
output [31:0] mem_data_o /*verilator public*/;
input [3:0] mem_wr_i /*verilator public*/;
input mem_rd_i /*verilator public*/;
input mem_burst_i /*verilator public*/;
output mem_ack_o /*verilator public*/;
output mem_accept_o /*verilator public*/;
output [31:0] out0_addr_o /*verilator public*/;
output [31:0] out0_data_o /*verilator public*/;
input [31:0] out0_data_i /*verilator public*/;
output [3:0] out0_wr_o /*verilator public*/;
output out0_rd_o /*verilator public*/;
output out0_burst_o /*verilator public*/;
input out0_ack_i /*verilator public*/;
input out0_accept_i /*verilator public*/;
output [31:0] out1_addr_o /*verilator public*/;
output [31:0] out1_data_o /*verilator public*/;
input [31:0] out1_data_i /*verilator public*/;
output [3:0] out1_wr_o /*verilator public*/;
output out1_rd_o /*verilator public*/;
output out1_burst_o /*verilator public*/;
input out1_ack_i /*verilator public*/;
input out1_accept_i /*verilator public*/;
output [31:0] out2_addr_o /*verilator public*/;
output [31:0] out2_data_o /*verilator public*/;
input [31:0] out2_data_i /*verilator public*/;
output [3:0] out2_wr_o /*verilator public*/;
output out2_rd_o /*verilator public*/;
output out2_burst_o /*verilator public*/;
input out2_ack_i /*verilator public*/;
input out2_accept_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
 
// Output Signals
reg mem_ack_o;
reg mem_accept_o;
reg [31:0] mem_data_o;
 
reg [31:0] out0_addr_o;
reg [31:0] out0_data_o;
reg [3:0] out0_wr_o;
reg out0_rd_o;
reg out0_burst_o;
reg [31:0] out1_addr_o;
reg [31:0] out1_data_o;
reg [3:0] out1_wr_o;
reg out1_rd_o;
reg out1_burst_o;
reg [31:0] out2_addr_o;
reg [31:0] out2_data_o;
reg [3:0] out2_wr_o;
reg out2_rd_o;
reg out2_burst_o;
 
//-----------------------------------------------------------------
// Memory Map
//-----------------------------------------------------------------
always @ (mem_addr_i or mem_wr_i or mem_rd_i or mem_data_i or mem_burst_i)
begin
 
out0_addr_o = 32'h00000000;
out0_wr_o = 4'b0000;
out0_rd_o = 1'b0;
out0_data_o = 32'h00000000;
out0_burst_o = 1'b0;
out1_addr_o = 32'h00000000;
out1_wr_o = 4'b0000;
out1_rd_o = 1'b0;
out1_data_o = 32'h00000000;
out1_burst_o = 1'b0;
out2_addr_o = 32'h00000000;
out2_wr_o = 4'b0000;
out2_rd_o = 1'b0;
out2_data_o = 32'h00000000;
out2_burst_o = 1'b0;
 
case (mem_addr_i[ADDR_MUX_START+2-1:ADDR_MUX_START])
 
2'd0:
begin
out0_addr_o = mem_addr_i;
out0_wr_o = mem_wr_i;
out0_rd_o = mem_rd_i;
out0_data_o = mem_data_i;
out0_burst_o = mem_burst_i;
end
2'd1:
begin
out1_addr_o = mem_addr_i;
out1_wr_o = mem_wr_i;
out1_rd_o = mem_rd_i;
out1_data_o = mem_data_i;
out1_burst_o = mem_burst_i;
end
2'd2:
begin
out2_addr_o = mem_addr_i;
out2_wr_o = mem_wr_i;
out2_rd_o = mem_rd_i;
out2_data_o = mem_data_i;
out2_burst_o = mem_burst_i;
end
 
default :
;
endcase
end
 
//-----------------------------------------------------------------
// Read Port
//-----------------------------------------------------------------
always @ *
begin
case (mem_addr_i[ADDR_MUX_START+2-1:ADDR_MUX_START])
 
2'd0:
begin
mem_data_o = out0_data_i;
mem_accept_o = out0_accept_i;
mem_ack_o = out0_ack_i;
end
2'd1:
begin
mem_data_o = out1_data_i;
mem_accept_o = out1_accept_i;
mem_ack_o = out1_ack_i;
end
2'd2:
begin
mem_data_o = out2_data_i;
mem_accept_o = out2_accept_i;
mem_ack_o = out2_ack_i;
end
 
default :
begin
mem_data_o = 32'h00000000;
mem_accept_o = 1'b0;
mem_ack_o = 1'b0;
end
endcase
end
 
endmodule
/rtl/soc/soc.v
0,0 → 1,266
 
//-----------------------------------------------------------------
// Module:
//-----------------------------------------------------------------
module soc
(
// General - Clocking & Reset
clk_i,
rst_i,
ext_intr_i,
intr_o,
 
 
 
 
 
 
 
 
 
// Memory interface
io_addr_i,
io_data_i,
io_data_o,
io_wr_i,
io_rd_i
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] CLK_KHZ = 12288;
parameter [31:0] UART_BAUD = 115200;
parameter [31:0] SPI_FLASH_CLK_KHZ = (12288/2);
parameter SD_CLK_KHZ = 8000;
parameter [31:0] EXTERNAL_INTERRUPTS = 1;
parameter SYSTICK_INTR_MS = 1;
parameter ENABLE_SYSTICK_TIMER = "ENABLED";
parameter ENABLE_HIGHRES_TIMER = "ENABLED";
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
input rst_i /*verilator public*/;
input [(EXTERNAL_INTERRUPTS - 1):0] ext_intr_i /*verilator public*/;
output intr_o /*verilator public*/;
 
 
// Memory Port
input [31:0] io_addr_i /*verilator public*/;
input [31:0] io_data_i /*verilator public*/;
output [31:0] io_data_o /*verilator public*/;
input [3:0] io_wr_i /*verilator public*/;
input io_rd_i /*verilator public*/;
 
 
 
 
 
 
 
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
 
 
 
 
 
 
 
wire [7:0] timer_addr;
wire [31:0] timer_data_o;
wire [31:0] timer_data_i;
wire [3:0] timer_wr;
wire timer_rd;
wire timer_intr_systick;
wire timer_intr_hires;
 
wire [7:0] intr_addr;
wire [31:0] intr_data_o;
wire [31:0] intr_data_i;
wire [3:0] intr_wr;
wire intr_rd;
 
//-----------------------------------------------------------------
// Peripheral Interconnect
//-----------------------------------------------------------------
soc_pif8
u2_soc
(
// General - Clocking & Reset
.clk_i(clk_i),
.rst_i(rst_i),
 
// I/O bus (from mem_mux)
// 0x12000000 - 0x12FFFFFF
.io_addr_i(io_addr_i),
.io_data_i(io_data_i),
.io_data_o(io_data_o),
.io_wr_i(io_wr_i),
.io_rd_i(io_rd_i),
 
// Peripherals
// Unused = 0x12000000 - 0x120000FF
.periph0_addr_o(/*open*/),
.periph0_data_o(/*open*/),
.periph0_data_i(32'h00000000),
.periph0_wr_o(/*open*/),
.periph0_rd_o(/*open*/),
 
// Timer = 0x12000100 - 0x120001FF
.periph1_addr_o(timer_addr),
.periph1_data_o(timer_data_o),
.periph1_data_i(timer_data_i),
.periph1_wr_o(timer_wr),
.periph1_rd_o(timer_rd),
 
// Interrupt Controller = 0x12000200 - 0x120002FF
.periph2_addr_o(intr_addr),
.periph2_data_o(intr_data_o),
.periph2_data_i(intr_data_i),
.periph2_wr_o(intr_wr),
.periph2_rd_o(intr_rd),
 
// Unused = 0x12000300 - 0x120003FF
.periph3_addr_o(/*open*/),
.periph3_data_o(/*open*/),
.periph3_data_i(32'h00000000),
.periph3_wr_o(/*open*/),
.periph3_rd_o(/*open*/),
 
// Unused = 0x12000400 - 0x120004FF
.periph4_addr_o(/*open*/),
.periph4_data_o(/*open*/),
.periph4_data_i(32'h00000000),
.periph4_wr_o(/*open*/),
.periph4_rd_o(/*open*/),
 
// Unused = 0x12000500 - 0x120005FF
.periph5_addr_o(/*open*/),
.periph5_data_o(/*open*/),
.periph5_data_i(32'h00000000),
.periph5_wr_o(/*open*/),
.periph5_rd_o(/*open*/),
 
// Unused = 0x12000600 - 0x120006FF
.periph6_addr_o(/*open*/),
.periph6_data_o(/*open*/),
.periph6_data_i(32'h00000000),
.periph6_wr_o(/*open*/),
.periph6_rd_o(/*open*/),
 
// Unused = 0x12000700 - 0x120007FF
.periph7_addr_o(/*open*/),
.periph7_data_o(/*open*/),
.periph7_data_i(32'h00000000),
.periph7_wr_o(/*open*/),
.periph7_rd_o(/*open*/)
);
 
//-----------------------------------------------------------------
// Memory master arbiter
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// UART
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// GPIO
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// SPI Flash Master
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// DMA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// SD
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Generic Register
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Timer
//-----------------------------------------------------------------
timer_periph
#(
.CLK_KHZ(CLK_KHZ),
.SYSTICK_INTR_MS(SYSTICK_INTR_MS),
.ENABLE_SYSTICK_TIMER(ENABLE_SYSTICK_TIMER),
.ENABLE_HIGHRES_TIMER(ENABLE_HIGHRES_TIMER)
)
u5_timer
(
.clk_i(clk_i),
.rst_i(rst_i),
.intr_systick_o(timer_intr_systick),
.intr_hires_o(timer_intr_hires),
.addr_i(timer_addr),
.data_o(timer_data_i),
.data_i(timer_data_o),
.wr_i(timer_wr),
.rd_i(timer_rd)
);
 
//-----------------------------------------------------------------
// Interrupt Controller
//-----------------------------------------------------------------
intr_periph
#(
.EXTERNAL_INTERRUPTS(EXTERNAL_INTERRUPTS)
)
u6_intr
(
.clk_i(clk_i),
.rst_i(rst_i),
.intr_o(intr_o),
 
.intr0_i(1'b0),
 
.intr1_i(timer_intr_systick),
.intr2_i(timer_intr_hires),
.intr3_i(1'b0),
 
.intr4_i(1'b0),
 
.intr5_i(1'b0),
 
.intr6_i(1'b0),
 
.intr7_i(1'b0),
.intr_ext_i(ext_intr_i),
 
.addr_i(intr_addr),
.data_o(intr_data_i),
.data_i(intr_data_o),
.wr_i(intr_wr),
.rd_i(intr_rd)
);
 
//-------------------------------------------------------------------
// Hooks for debug
//-------------------------------------------------------------------
`ifdef verilator
function [0:0] get_uart_wr;
// verilator public
get_uart_wr = 1'b0;
endfunction
function [7:0] get_uart_data;
// verilator public
get_uart_data = 8'b0;
endfunction
`endif
 
endmodule
/rtl/soc/cpu_if.v
0,0 → 1,232
 
//-----------------------------------------------------------------
// Module:
//-----------------------------------------------------------------
module cpu_if
(
// General - Clocking & Reset
clk_i,
rst_i,
 
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF)
imem0_addr_o,
imem0_rd_o,
imem0_burst_o,
imem0_data_in_i,
imem0_accept_i,
imem0_ack_i,
 
// Data Memory 0 (0x10000000 - 0x10FFFFFF)
dmem0_addr_o,
dmem0_data_o,
dmem0_data_i,
dmem0_wr_o,
dmem0_rd_o,
dmem0_burst_o,
dmem0_accept_i,
dmem0_ack_i,
// Data Memory 1 (0x11000000 - 0x11FFFFFF)
dmem1_addr_o,
dmem1_data_o,
dmem1_data_i,
dmem1_wr_o,
dmem1_rd_o,
dmem1_burst_o,
dmem1_accept_i,
dmem1_ack_i,
// Data Memory 2 (0x12000000 - 0x12FFFFFF)
dmem2_addr_o,
dmem2_data_o,
dmem2_data_i,
dmem2_wr_o,
dmem2_rd_o,
dmem2_burst_o,
dmem2_accept_i,
dmem2_ack_i,
 
fault_o,
break_o,
intr_i,
nmi_i
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] CLK_KHZ = 12288;
parameter ENABLE_ICACHE = "ENABLED";
parameter ENABLE_DCACHE = "DISABLED";
parameter BOOT_VECTOR = 0;
parameter ISR_VECTOR = 0;
parameter REGISTER_FILE_TYPE = "SIMULATION";
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
input rst_i /*verilator public*/;
 
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF)
output [31:0] imem0_addr_o /*verilator public*/;
output imem0_rd_o /*verilator public*/;
output imem0_burst_o /*verilator public*/;
input [31:0] imem0_data_in_i /*verilator public*/;
input imem0_accept_i /*verilator public*/;
input imem0_ack_i /*verilator public*/;
 
// Data Memory 0 (0x10000000 - 0x10FFFFFF)
output [31:0] dmem0_addr_o /*verilator public*/;
output [31:0] dmem0_data_o /*verilator public*/;
input [31:0] dmem0_data_i /*verilator public*/;
output [3:0] dmem0_wr_o /*verilator public*/;
output dmem0_rd_o /*verilator public*/;
output dmem0_burst_o /*verilator public*/;
input dmem0_accept_i /*verilator public*/;
input dmem0_ack_i /*verilator public*/;
// Data Memory 1 (0x11000000 - 0x11FFFFFF)
output [31:0] dmem1_addr_o /*verilator public*/;
output [31:0] dmem1_data_o /*verilator public*/;
input [31:0] dmem1_data_i /*verilator public*/;
output [3:0] dmem1_wr_o /*verilator public*/;
output dmem1_rd_o /*verilator public*/;
output dmem1_burst_o /*verilator public*/;
input dmem1_accept_i /*verilator public*/;
input dmem1_ack_i /*verilator public*/;
// Data Memory 2 (0x12000000 - 0x12FFFFFF)
output [31:0] dmem2_addr_o /*verilator public*/;
output [31:0] dmem2_data_o /*verilator public*/;
input [31:0] dmem2_data_i /*verilator public*/;
output [3:0] dmem2_wr_o /*verilator public*/;
output dmem2_rd_o /*verilator public*/;
output dmem2_burst_o /*verilator public*/;
input dmem2_accept_i /*verilator public*/;
input dmem2_ack_i /*verilator public*/;
 
output fault_o /*verilator public*/;
output break_o /*verilator public*/;
input nmi_i /*verilator public*/;
input intr_i /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
wire [31:0] cpu_address;
wire [3:0] cpu_wr;
wire cpu_rd;
wire cpu_burst;
wire [31:0] cpu_data_w;
wire [31:0] cpu_data_r;
wire cpu_accept;
wire cpu_ack;
wire [31:0] imem_address;
wire [31:0] imem_data;
wire imem_rd;
wire imem_burst;
wire imem_ack;
wire imem_accept;
 
//-----------------------------------------------------------------
// CPU core
//-----------------------------------------------------------------
cpu
#(
.BOOT_VECTOR(BOOT_VECTOR),
.ISR_VECTOR(ISR_VECTOR),
.REGISTER_FILE_TYPE(REGISTER_FILE_TYPE),
.ENABLE_ICACHE(ENABLE_ICACHE),
.ENABLE_DCACHE(ENABLE_DCACHE)
)
u1_cpu
(
.clk_i(clk_i),
.rst_i(rst_i),
 
.intr_i(intr_i),
.nmi_i(nmi_i),
// Status
.fault_o(fault_o),
.break_o(break_o),
// Instruction memory
.imem_addr_o(imem_address),
.imem_rd_o(imem_rd),
.imem_burst_o(imem_burst),
.imem_data_in_i(imem_data),
.imem_accept_i(imem_accept),
.imem_ack_i(imem_ack),
// Data memory
.dmem_addr_o(cpu_address),
.dmem_data_out_o(cpu_data_w),
.dmem_data_in_i(cpu_data_r),
.dmem_wr_o(cpu_wr),
.dmem_rd_o(cpu_rd),
.dmem_burst_o(cpu_burst),
.dmem_accept_i(cpu_accept),
.dmem_ack_i(cpu_ack)
);
 
//-----------------------------------------------------------------
// Instruction Memory MUX
//-----------------------------------------------------------------
 
assign imem0_addr_o = imem_address;
assign imem0_rd_o = imem_rd;
assign imem0_burst_o = imem_burst;
assign imem_data = imem0_data_in_i;
assign imem_accept = imem0_accept_i;
assign imem_ack = imem0_ack_i;
 
 
//-----------------------------------------------------------------
// Data Memory MUX
//-----------------------------------------------------------------
dmem_mux3
#(
.ADDR_MUX_START(24)
)
u_dmux
(
// Outputs
// 0x10000000 - 0x10FFFFFF
.out0_addr_o(dmem0_addr_o),
.out0_data_o(dmem0_data_o),
.out0_data_i(dmem0_data_i),
.out0_wr_o(dmem0_wr_o),
.out0_rd_o(dmem0_rd_o),
.out0_burst_o(dmem0_burst_o),
.out0_ack_i(dmem0_ack_i),
.out0_accept_i(dmem0_accept_i),
// 0x11000000 - 0x11FFFFFF
.out1_addr_o(dmem1_addr_o),
.out1_data_o(dmem1_data_o),
.out1_data_i(dmem1_data_i),
.out1_wr_o(dmem1_wr_o),
.out1_rd_o(dmem1_rd_o),
.out1_burst_o(dmem1_burst_o),
.out1_ack_i(dmem1_ack_i),
.out1_accept_i(dmem1_accept_i),
// 0x12000000 - 0x12FFFFFF
.out2_addr_o(dmem2_addr_o),
.out2_data_o(dmem2_data_o),
.out2_data_i(dmem2_data_i),
.out2_wr_o(dmem2_wr_o),
.out2_rd_o(dmem2_rd_o),
.out2_burst_o(dmem2_burst_o),
.out2_ack_i(dmem2_ack_i),
.out2_accept_i(dmem2_accept_i),
 
// Input - CPU core bus
.mem_addr_i(cpu_address),
.mem_data_i(cpu_data_w),
.mem_data_o(cpu_data_r),
.mem_wr_i(cpu_wr),
.mem_rd_i(cpu_rd),
.mem_burst_i(cpu_burst),
.mem_ack_o(cpu_ack),
.mem_accept_o(cpu_accept)
);
 
endmodule
/rtl/soc/soc_pif8.v
0,0 → 1,332
 
//-----------------------------------------------------------------
// Module:
//-----------------------------------------------------------------
module soc_pif8
(
// General - Clocking & Reset
clk_i,
rst_i,
 
// Peripherals
periph0_addr_o,
periph0_data_o,
periph0_data_i,
periph0_wr_o,
periph0_rd_o,
periph1_addr_o,
periph1_data_o,
periph1_data_i,
periph1_wr_o,
periph1_rd_o,
periph2_addr_o,
periph2_data_o,
periph2_data_i,
periph2_wr_o,
periph2_rd_o,
periph3_addr_o,
periph3_data_o,
periph3_data_i,
periph3_wr_o,
periph3_rd_o,
periph4_addr_o,
periph4_data_o,
periph4_data_i,
periph4_wr_o,
periph4_rd_o,
periph5_addr_o,
periph5_data_o,
periph5_data_i,
periph5_wr_o,
periph5_rd_o,
periph6_addr_o,
periph6_data_o,
periph6_data_i,
periph6_wr_o,
periph6_rd_o,
periph7_addr_o,
periph7_data_o,
periph7_data_i,
periph7_wr_o,
periph7_rd_o,
 
// I/O bus
io_addr_i,
io_data_i,
io_data_o,
io_wr_i,
io_rd_i
);
 
//-----------------------------------------------------------------
// I/O
//-----------------------------------------------------------------
input clk_i /*verilator public*/;
input rst_i /*verilator public*/;
 
input [31:0] io_addr_i /*verilator public*/;
output [31:0] io_data_o /*verilator public*/;
input [31:0] io_data_i /*verilator public*/;
input [3:0] io_wr_i /*verilator public*/;
input io_rd_i /*verilator public*/;
 
output [7:0] periph0_addr_o /*verilator public*/;
output [31:0] periph0_data_o /*verilator public*/;
input [31:0] periph0_data_i /*verilator public*/;
output [3:0] periph0_wr_o /*verilator public*/;
output periph0_rd_o /*verilator public*/;
output [7:0] periph1_addr_o /*verilator public*/;
output [31:0] periph1_data_o /*verilator public*/;
input [31:0] periph1_data_i /*verilator public*/;
output [3:0] periph1_wr_o /*verilator public*/;
output periph1_rd_o /*verilator public*/;
output [7:0] periph2_addr_o /*verilator public*/;
output [31:0] periph2_data_o /*verilator public*/;
input [31:0] periph2_data_i /*verilator public*/;
output [3:0] periph2_wr_o /*verilator public*/;
output periph2_rd_o /*verilator public*/;
output [7:0] periph3_addr_o /*verilator public*/;
output [31:0] periph3_data_o /*verilator public*/;
input [31:0] periph3_data_i /*verilator public*/;
output [3:0] periph3_wr_o /*verilator public*/;
output periph3_rd_o /*verilator public*/;
output [7:0] periph4_addr_o /*verilator public*/;
output [31:0] periph4_data_o /*verilator public*/;
input [31:0] periph4_data_i /*verilator public*/;
output [3:0] periph4_wr_o /*verilator public*/;
output periph4_rd_o /*verilator public*/;
output [7:0] periph5_addr_o /*verilator public*/;
output [31:0] periph5_data_o /*verilator public*/;
input [31:0] periph5_data_i /*verilator public*/;
output [3:0] periph5_wr_o /*verilator public*/;
output periph5_rd_o /*verilator public*/;
output [7:0] periph6_addr_o /*verilator public*/;
output [31:0] periph6_data_o /*verilator public*/;
input [31:0] periph6_data_i /*verilator public*/;
output [3:0] periph6_wr_o /*verilator public*/;
output periph6_rd_o /*verilator public*/;
output [7:0] periph7_addr_o /*verilator public*/;
output [31:0] periph7_data_o /*verilator public*/;
input [31:0] periph7_data_i /*verilator public*/;
output [3:0] periph7_wr_o /*verilator public*/;
output periph7_rd_o /*verilator public*/;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [3:0] r_mem_sel;
 
reg [31:0] io_data_o;
 
reg [7:0] periph0_addr_o;
reg [31:0] periph0_data_o;
reg [3:0] periph0_wr_o;
reg periph0_rd_o;
reg [7:0] periph1_addr_o;
reg [31:0] periph1_data_o;
reg [3:0] periph1_wr_o;
reg periph1_rd_o;
reg [7:0] periph2_addr_o;
reg [31:0] periph2_data_o;
reg [3:0] periph2_wr_o;
reg periph2_rd_o;
reg [7:0] periph3_addr_o;
reg [31:0] periph3_data_o;
reg [3:0] periph3_wr_o;
reg periph3_rd_o;
reg [7:0] periph4_addr_o;
reg [31:0] periph4_data_o;
reg [3:0] periph4_wr_o;
reg periph4_rd_o;
reg [7:0] periph5_addr_o;
reg [31:0] periph5_data_o;
reg [3:0] periph5_wr_o;
reg periph5_rd_o;
reg [7:0] periph6_addr_o;
reg [31:0] periph6_data_o;
reg [3:0] periph6_wr_o;
reg periph6_rd_o;
reg [7:0] periph7_addr_o;
reg [31:0] periph7_data_o;
reg [3:0] periph7_wr_o;
reg periph7_rd_o;
 
//-----------------------------------------------------------------
// Memory Map
//-----------------------------------------------------------------
always @ (io_addr_i or io_wr_i or io_rd_i or io_data_i)
begin
 
periph0_addr_o = 8'h00;
periph0_wr_o = 4'b0000;
periph0_rd_o = 1'b0;
periph0_data_o = 32'h00000000;
periph1_addr_o = 8'h00;
periph1_wr_o = 4'b0000;
periph1_rd_o = 1'b0;
periph1_data_o = 32'h00000000;
periph2_addr_o = 8'h00;
periph2_wr_o = 4'b0000;
periph2_rd_o = 1'b0;
periph2_data_o = 32'h00000000;
periph3_addr_o = 8'h00;
periph3_wr_o = 4'b0000;
periph3_rd_o = 1'b0;
periph3_data_o = 32'h00000000;
periph4_addr_o = 8'h00;
periph4_wr_o = 4'b0000;
periph4_rd_o = 1'b0;
periph4_data_o = 32'h00000000;
periph5_addr_o = 8'h00;
periph5_wr_o = 4'b0000;
periph5_rd_o = 1'b0;
periph5_data_o = 32'h00000000;
periph6_addr_o = 8'h00;
periph6_wr_o = 4'b0000;
periph6_rd_o = 1'b0;
periph6_data_o = 32'h00000000;
periph7_addr_o = 8'h00;
periph7_wr_o = 4'b0000;
periph7_rd_o = 1'b0;
periph7_data_o = 32'h00000000;
 
// Decode 4-bit peripheral select
case (io_addr_i[11:8])
 
// Peripheral 0
4'd 0 :
begin
periph0_addr_o = io_addr_i[7:0];
periph0_wr_o = io_wr_i;
periph0_rd_o = io_rd_i;
periph0_data_o = io_data_i;
end
// Peripheral 1
4'd 1 :
begin
periph1_addr_o = io_addr_i[7:0];
periph1_wr_o = io_wr_i;
periph1_rd_o = io_rd_i;
periph1_data_o = io_data_i;
end
// Peripheral 2
4'd 2 :
begin
periph2_addr_o = io_addr_i[7:0];
periph2_wr_o = io_wr_i;
periph2_rd_o = io_rd_i;
periph2_data_o = io_data_i;
end
// Peripheral 3
4'd 3 :
begin
periph3_addr_o = io_addr_i[7:0];
periph3_wr_o = io_wr_i;
periph3_rd_o = io_rd_i;
periph3_data_o = io_data_i;
end
// Peripheral 4
4'd 4 :
begin
periph4_addr_o = io_addr_i[7:0];
periph4_wr_o = io_wr_i;
periph4_rd_o = io_rd_i;
periph4_data_o = io_data_i;
end
// Peripheral 5
4'd 5 :
begin
periph5_addr_o = io_addr_i[7:0];
periph5_wr_o = io_wr_i;
periph5_rd_o = io_rd_i;
periph5_data_o = io_data_i;
end
// Peripheral 6
4'd 6 :
begin
periph6_addr_o = io_addr_i[7:0];
periph6_wr_o = io_wr_i;
periph6_rd_o = io_rd_i;
periph6_data_o = io_data_i;
end
// Peripheral 7
4'd 7 :
begin
periph7_addr_o = io_addr_i[7:0];
periph7_wr_o = io_wr_i;
periph7_rd_o = io_rd_i;
periph7_data_o = io_data_i;
end
 
default :
;
endcase
end
 
//-----------------------------------------------------------------
// Read Port
//-----------------------------------------------------------------
always @ *
begin
case (r_mem_sel)
 
// Peripheral 0
4'd 0 :
begin
io_data_o = periph0_data_i;
end
// Peripheral 1
4'd 1 :
begin
io_data_o = periph1_data_i;
end
// Peripheral 2
4'd 2 :
begin
io_data_o = periph2_data_i;
end
// Peripheral 3
4'd 3 :
begin
io_data_o = periph3_data_i;
end
// Peripheral 4
4'd 4 :
begin
io_data_o = periph4_data_i;
end
// Peripheral 5
4'd 5 :
begin
io_data_o = periph5_data_i;
end
// Peripheral 6
4'd 6 :
begin
io_data_o = periph6_data_i;
end
// Peripheral 7
4'd 7 :
begin
io_data_o = periph7_data_i;
end
 
default :
begin
io_data_o = 32'h00000000;
end
endcase
end
 
//-----------------------------------------------------------------
// Registered peripheral select
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
r_mem_sel <= 4'h0;
else
r_mem_sel <= io_addr_i[11:8];
end
 
endmodule
/rtl/cpu/altor32_dcache.v
0,0 → 1,684
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module - Data Cache (write back)
//-----------------------------------------------------------------
module altor32_dcache
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
input flush_i /*verilator public*/,
 
// Input (CPU)
input [31:0] address_i /*verilator public*/,
output [31:0] data_o /*verilator public*/,
input [31:0] data_i /*verilator public*/,
input rd_i /*verilator public*/,
input [3:0] wr_i /*verilator public*/,
output accept_o /*verilator public*/,
output ack_o /*verilator public*/,
 
// Output (Memory)
output [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output [31:0] mem_data_o /*verilator public*/,
output mem_burst_o /*verilator public*/,
output mem_rd_o /*verilator public*/,
output [3:0] mem_wr_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
parameter CACHE_LINE_SIZE_BYTES = 2 ** CACHE_LINE_SIZE_WIDTH; /* 32 bytes / 8 words per line */
parameter CACHE_LINE_ADDR_WIDTH = 8; /* 256 lines */
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit = 8 words */
parameter CACHE_TAG_ENTRIES = 2 ** CACHE_LINE_ADDR_WIDTH ; /* 256 tag entries */
parameter CACHE_DSIZE = CACHE_LINE_ADDR_WIDTH * CACHE_LINE_SIZE_BYTES; /* 8KB data */
parameter CACHE_DWIDTH = CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 2; /* 11-bits */
 
parameter CACHE_TAG_WIDTH = 16; /* 16-bit tag entry size */
parameter CACHE_TAG_LINE_ADDR_WIDTH = CACHE_TAG_WIDTH - 2; /* 14 bits of data (tag entry size minus valid/dirty bit) */
 
parameter CACHE_TAG_ADDR_LOW = CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH;
parameter CACHE_TAG_ADDR_HIGH = CACHE_TAG_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH - 1;
 
// Tag fields
parameter CACHE_TAG_DIRTY_BIT = 14;
parameter CACHE_TAG_VALID_BIT = 15;
parameter ADDR_NO_CACHE_BIT = 25;
parameter ADDR_CACHE_BYPASS_BIT = 31;
 
// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
// |--------------| | | | | | | | | | | | | | | | |
// +--------------------+ +-------------------+ +-----------+
// Tag entry Line address Address
// (15-bits) (8-bits) within line
// (5-bits)
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry;
wire [CACHE_TAG_WIDTH-1:0] tag_data_out;
reg [CACHE_TAG_WIDTH-1:0] tag_data_in;
reg tag_wr;
 
wire [CACHE_DWIDTH-1:0] cache_address;
wire [31:0] cache_data_r;
reg [31:0] cache_data_w;
reg [3:0] cache_wr;
 
wire [31:2] cache_update_addr;
wire [31:0] cache_update_data_w;
wire [31:0] cache_update_data_r;
wire cache_update_wr;
 
reg ack;
 
reg fill;
reg evict;
wire done;
 
reg [31:0] data_w;
wire [31:0] data_r;
reg data_rd;
reg [3:0] data_wr;
 
reg req_rd;
reg [3:0] req_wr;
reg req_ack;
reg [31:0] req_address;
 
reg req_flush;
reg flush_single;
 
wire [31:0] line_address;
 
wire [31:0] muxed_address = (state == STATE_IDLE) ? address_i : req_address;
 
// Current state
parameter STATE_IDLE = 0;
parameter STATE_SINGLE = 1;
parameter STATE_CHECK = 2;
parameter STATE_FETCH = 3;
parameter STATE_WAIT = 4;
parameter STATE_WAIT2 = 5;
parameter STATE_WRITE = 6;
parameter STATE_SINGLE_READY= 7;
parameter STATE_EVICTING = 8;
parameter STATE_UPDATE = 9;
parameter STATE_FLUSH1 = 10;
parameter STATE_FLUSH2 = 11;
parameter STATE_FLUSH3 = 12;
parameter STATE_FLUSH4 = 13;
reg [3:0] state;
 
assign tag_entry = muxed_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
assign cache_address = {tag_entry, muxed_address[CACHE_LINE_SIZE_WIDTH-1:2]};
 
assign data_o = (state == STATE_SINGLE_READY) ? data_r : cache_data_r;
assign accept_o = (state == STATE_IDLE);
 
 
wire valid = tag_data_out[CACHE_TAG_VALID_BIT];
wire dirty = tag_data_out[CACHE_TAG_DIRTY_BIT];
 
// Access is cacheable?
wire cacheable = ~muxed_address[ADDR_NO_CACHE_BIT] & ~muxed_address[ADDR_CACHE_BYPASS_BIT];
 
// Cache hit?
wire hit = cacheable & valid & (muxed_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]) & (state == STATE_CHECK);
 
assign ack_o = ack | hit;
 
assign line_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] = tag_entry;
assign line_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] = tag_data_out[13:0];
assign line_address[CACHE_LINE_SIZE_WIDTH-1:0] = {CACHE_LINE_SIZE_WIDTH{1'b0}};
 
//-----------------------------------------------------------------
// Control logic
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
data_w <= 32'h00000000;
data_wr <= 4'h0;
data_rd <= 1'b0;
req_address <= 32'h00000000;
req_ack <= 1'b0;
req_wr <= 4'h0;
req_rd <= 1'b0;
tag_wr <= 1'b0;
req_flush <= 1'b0;
flush_single <= 1'b0;
fill <= 1'b0;
evict <= 1'b0;
cache_data_w <= 32'h00000000;
cache_wr <= 4'b0;
ack <= 1'b0;
state <= STATE_IDLE;
end
else
begin
ack <= 1'b0;
tag_wr <= 1'b0;
fill <= 1'b0;
evict <= 1'b0;
cache_wr <= 4'b0;
data_wr <= 4'b0;
data_rd <= 1'b0;
 
if (flush_i)
req_flush <= 1'b1;
 
case (state)
 
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Read (uncacheable)
if (rd_i & ~cacheable)
begin
// Start read single from memory
req_address <= address_i;
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
data_rd <= 1'b1;
req_rd <= 1'b1;
req_wr <= 4'b0;
req_ack <= 1'b1;
state <= STATE_SINGLE;
end
// Read (cacheable)
else if (rd_i)
begin
req_address <= address_i;
req_rd <= 1'b1;
req_wr <= 4'b0;
req_ack <= 1'b1;
state <= STATE_CHECK;
end
// Write (uncacheable)
else if (wr_i != 4'b0000 & ~cacheable)
begin
// Perform write single
req_address <= address_i;
req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
data_w <= data_i;
data_wr <= wr_i;
req_wr <= wr_i;
req_rd <= 1'b0;
req_ack <= 1'b1;
state <= STATE_SINGLE;
end
// Write (cacheable)
else if (wr_i != 4'b0000)
begin
req_address <= address_i;
data_w <= data_i;
req_wr <= wr_i;
req_rd <= 1'b0;
req_ack <= 1'b0;
 
// Early ACK
ack <= 1'b1;
 
state <= STATE_WRITE;
end
// Cache flush request
else if (flush_i | req_flush)
begin
// Set to first line address
req_address <= 32'h00000000;
req_flush <= 1'b0;
req_ack <= 1'b0;
flush_single<= 1'b0;
state <= STATE_FLUSH2;
end
end
//-----------------------------------------
// WRITE - Wait for write-thru to complete
//-----------------------------------------
STATE_WRITE :
begin
// Cache hit
if (valid &&
(req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]))
begin
// Update line already in cache
cache_data_w <= data_w;
cache_wr <= req_wr;
 
// Mark line as dirty
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
 
state <= STATE_WAIT2;
end
// Cache dirty
else if (valid & dirty)
begin
// Evict cache line
evict <= 1'b1;
state <= STATE_EVICTING;
end
// Cache miss
else
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Fill cache line
fill <= 1'b1;
state <= STATE_UPDATE;
end
end
//-----------------------------------------
// EVICTING - Evicting cache line
//-----------------------------------------
STATE_EVICTING:
begin
// Data ready from memory?
if (done)
begin
// Update tag memory with this new line's details
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Fill cache line
fill <= 1'b1;
 
// Evict for read?
if (req_rd)
state <= STATE_FETCH;
// Evict for write
else
state <= STATE_UPDATE;
end
end
//-----------------------------------------
// UPDATE - Update fetched cache line
//-----------------------------------------
STATE_UPDATE:
begin
// Data ready from memory?
if (done)
begin
// Update line already in cache
cache_data_w <= data_w;
cache_wr <= req_wr;
 
// Mark line as dirty
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
tag_wr <= 1'b1;
 
state <= STATE_WAIT2;
end
end
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache hit
if (valid &&
(req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]))
begin
state <= STATE_IDLE;
end
// Cache dirty
else if (valid & dirty)
begin
// Evict cache line
evict <= 1'b1;
state <= STATE_EVICTING;
end
// Cache miss
else
begin
// Update tag memory with this line's details
tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Fill cache line
fill <= 1'b1;
state <= STATE_FETCH;
end
end
//-----------------------------------------
// FETCH_SINGLE - Single access to memory
//-----------------------------------------
STATE_SINGLE:
begin
// Data ready from memory?
if (done)
begin
// Single WRITE?
if (~req_rd)
begin
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
// Dirty? Write back
else if (valid & dirty)
begin
// Evict cache line
evict <= 1'b1;
flush_single<= 1'b1;
state <= STATE_FLUSH4;
end
// Valid line, invalidate
else if (valid)
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
 
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
else
begin
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
end
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Cache line filled?
if (done)
state <= STATE_WAIT;
end
//-----------------------------------------
// WAIT - Wait cycle
//-----------------------------------------
STATE_WAIT :
begin
// Allow extra wait state to handle write & read collision
state <= STATE_WAIT2;
end
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
begin
state <= STATE_IDLE;
ack <= req_ack;
end
//-----------------------------------------
// SINGLE_READY - Uncached access ready
//-----------------------------------------
STATE_SINGLE_READY :
begin
// Allow extra wait state to handle write & read collision
state <= STATE_IDLE;
end
//-----------------------------------------
// FLUSHx - Flush dirty lines & invalidate
//-----------------------------------------
STATE_FLUSH1 :
begin
if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
begin
req_ack <= 1'b0;
state <= STATE_WAIT;
end
else
begin
// Increment flush line address
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <=
req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] + 1;
 
state <= STATE_FLUSH2;
end
end
//-----------------------------------------
// FLUSH2 - Wait state
//-----------------------------------------
STATE_FLUSH2 :
begin
// Allow a cycle to read line state
state <= STATE_FLUSH3;
end
//-----------------------------------------
// FLUSH3 - Check if line dirty & flush
//-----------------------------------------
STATE_FLUSH3 :
begin
// Dirty line? Evict line first
if (dirty)
begin
// Evict cache line
evict <= 1'b1;
state <= STATE_FLUSH4;
end
// Not dirty? Just invalidate
else
begin
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_wr <= 1'b1;
 
if (flush_single)
state <= STATE_WAIT;
else
state <= STATE_FLUSH1;
end
end
//-----------------------------------------
// FLUSH4 - Wait for line flush to complete
//-----------------------------------------
STATE_FLUSH4 :
begin
// Cache line filled?
if (done)
begin
// Invalidate line
tag_data_in <= tag_data_out;
tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
tag_wr <= 1'b1;
 
if (flush_single)
begin
state <= STATE_SINGLE_READY;
ack <= req_ack;
end
else
state <= STATE_FLUSH1;
end
end
default:
;
endcase
end
end
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
 
altor32_dcache_mem_if
#(
.CACHE_LINE_SIZE_WIDTH(CACHE_LINE_SIZE_WIDTH),
.CACHE_LINE_WORDS_IDX_MAX(CACHE_LINE_WORDS_IDX_MAX)
)
u_mem_if
(
.clk_i(clk_i),
.rst_i(rst_i),
// Cache interface
.address_i(muxed_address),
.data_i(data_w),
.data_o(data_r),
.fill_i(fill),
.evict_i(evict),
.evict_addr_i(line_address),
.rd_single_i(data_rd),
.wr_single_i(data_wr),
.done_o(done),
 
// Cache memory (fill/evict)
.cache_addr_o(cache_update_addr),
.cache_data_o(cache_update_data_w),
.cache_data_i(cache_update_data_r),
.cache_wr_o(cache_update_wr),
// Memory interface (slave)
.mem_addr_o(mem_addr_o),
.mem_data_i(mem_data_i),
.mem_data_o(mem_data_o),
.mem_burst_o(mem_burst_o),
.mem_rd_o(mem_rd_o),
.mem_wr_o(mem_wr_o),
.mem_accept_i(mem_accept_i),
.mem_ack_i(mem_ack_i)
);
// Tag memory
altor32_ram_sp
#(
.WIDTH(CACHE_TAG_WIDTH),
.SIZE(CACHE_LINE_ADDR_WIDTH)
)
u1_tag_mem
(
.clk_i(clk_i),
.dat_o(tag_data_out),
.dat_i(tag_data_in),
.adr_i(tag_entry),
.wr_i(tag_wr)
);
// Data memory
altor32_ram_dp
#(
.WIDTH(8),
.SIZE(CACHE_DWIDTH)
)
u2_data_mem0
(
.aclk_i(clk_i),
.aadr_i(cache_address),
.adat_o(cache_data_r[7:0]),
.adat_i(cache_data_w[7:0]),
.awr_i(cache_wr[0]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
.bdat_o(cache_update_data_r[7:0]),
.bdat_i(cache_update_data_w[7:0]),
.bwr_i(cache_update_wr)
);
 
altor32_ram_dp
#(
.WIDTH(8),
.SIZE(CACHE_DWIDTH)
)
u2_data_mem1
(
.aclk_i(clk_i),
.aadr_i(cache_address),
.adat_o(cache_data_r[15:8]),
.adat_i(cache_data_w[15:8]),
.awr_i(cache_wr[1]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
.bdat_o(cache_update_data_r[15:8]),
.bdat_i(cache_update_data_w[15:8]),
.bwr_i(cache_update_wr)
);
 
altor32_ram_dp
#(
.WIDTH(8),
.SIZE(CACHE_DWIDTH)
)
u2_data_mem2
(
.aclk_i(clk_i),
.aadr_i(cache_address),
.adat_o(cache_data_r[23:16]),
.adat_i(cache_data_w[23:16]),
.awr_i(cache_wr[2]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
.bdat_o(cache_update_data_r[23:16]),
.bdat_i(cache_update_data_w[23:16]),
.bwr_i(cache_update_wr)
);
 
altor32_ram_dp
#(
.WIDTH(8),
.SIZE(CACHE_DWIDTH)
)
u2_data_mem3
(
.aclk_i(clk_i),
.aadr_i(cache_address),
.adat_o(cache_data_r[31:24]),
.adat_i(cache_data_w[31:24]),
.awr_i(cache_wr[3]),
.bclk_i(clk_i),
.badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
.bdat_o(cache_update_data_r[31:24]),
.bdat_i(cache_update_data_w[31:24]),
.bwr_i(cache_update_wr)
);
 
endmodule
/rtl/cpu/altor32_noicache.v
0,0 → 1,126
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Cache substitute (used when ICache disabled)
//-----------------------------------------------------------------
module altor32_noicache
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
// Processor interface
input rd_i /*verilator public*/,
input [31:0] pc_i /*verilator public*/,
output [31:0] instruction_o /*verilator public*/,
output valid_o /*verilator public*/,
// Memory interface (slave)
output reg [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output reg mem_burst_o /*verilator public*/,
output reg mem_rd_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
// Current state
parameter STATE_CHECK = 0;
parameter STATE_FETCH = 1;
reg [1:0] state;
 
assign valid_o = mem_ack_i;
assign instruction_o = mem_data_i;
 
//-----------------------------------------------------------------
// Control logic
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
mem_addr_o <= 32'h00000000;
mem_rd_o <= 1'b0;
mem_burst_o <= 1'b0;
state <= STATE_CHECK;
end
else
begin
if (mem_accept_i)
mem_rd_o <= 1'b0;
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Start fetch from memory
mem_addr_o <= pc_i;
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b0;
state <= STATE_FETCH;
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Data ready from memory?
if (mem_ack_i)
state <= STATE_CHECK;
end
default:
;
endcase
end
end
 
endmodule
 
/rtl/cpu/altor32_writeback.v
0,0 → 1,146
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Writeback
//-----------------------------------------------------------------
module altor32_writeback
(
// General
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
// Opcode
input [31:0] opcode_i /*verilator public*/,
 
// Register target
input [4:0] rd_i /*verilator public*/,
 
// ALU result
input [31:0] alu_result_i /*verilator public*/,
 
// Memory load result
input [31:0] mem_result_i /*verilator public*/,
input [1:0] mem_offset_i /*verilator public*/,
input mem_ready_i /*verilator public*/,
 
// Multiplier result
input mult_i /*verilator public*/,
input [31:0] mult_result_i /*verilator public*/,
 
// Outputs
output write_enable_o /*verilator public*/,
output [4:0] write_addr_o /*verilator public*/,
output [31:0] write_data_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
 
// Register address
reg [4:0] r_w_rd;
 
// Register writeback value
reg [31:0] r_result;
 
reg [7:0] r_opcode;
 
// Register writeback enable
reg r_w_write_rd;
 
//-------------------------------------------------------------------
// Writeback
//-------------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
r_w_write_rd <= 1'b1;
r_result <= 32'h00000000;
r_w_rd <= 5'b00000;
r_opcode <= 8'b0;
end
else
begin
r_w_write_rd <= 1'b0;
 
r_w_rd <= rd_i;
r_result <= alu_result_i;
 
r_opcode <= {2'b00,opcode_i[31:26]};
// Register writeback required?
if (rd_i != 5'b00000)
r_w_write_rd <= 1'b1;
end
end
 
//-------------------------------------------------------------------
// Load result resolve
//-------------------------------------------------------------------
wire load_insn;
wire [31:0] load_result;
 
altor32_lfu
u_lfu
(
// Opcode
.opcode_i(r_opcode),
 
// Memory load result
.mem_result_i(mem_result_i),
.mem_offset_i(mem_offset_i),
 
// Result
.load_result_o(load_result),
.load_insn_o(load_insn)
);
 
//-------------------------------------------------------------------
// Assignments
//-------------------------------------------------------------------
assign write_enable_o = load_insn ? (r_w_write_rd & mem_ready_i) : r_w_write_rd;
assign write_data_o = load_insn ? load_result : (mult_i ? mult_result_i : r_result);
assign write_addr_o = r_w_rd;
 
endmodule
/rtl/cpu/altor32_icache.v
0,0 → 1,390
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Instruction Cache
//-----------------------------------------------------------------
module altor32_icache
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
// Processor interface
input rd_i /*verilator public*/,
input [31:0] pc_i /*verilator public*/,
output [31:0] instruction_o /*verilator public*/,
output valid_o /*verilator public*/,
input invalidate_i /*verilator public*/,
 
// Status
output miss_o /*verilator public*/,
output busy_o /*verilator public*/,
 
// Memory interface (slave)
output [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output mem_burst_o /*verilator public*/,
output mem_rd_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
 
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
parameter CACHE_LINE_SIZE_BYTES = 2 ** CACHE_LINE_SIZE_WIDTH; /* 32 bytes / 4 words per line */
parameter CACHE_LINE_ADDR_WIDTH = 8; /* 256 lines */
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit = 111 */
parameter CACHE_TAG_ENTRIES = 2 ** CACHE_LINE_ADDR_WIDTH ; /* 256 tag entries */
parameter CACHE_DSIZE = CACHE_LINE_ADDR_WIDTH * CACHE_LINE_SIZE_BYTES; /* 8KB data */
parameter CACHE_DWIDTH = CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 2; /* 10-bits */
 
parameter CACHE_TAG_WIDTH = 16; /* 16-bit tag entry size */
parameter CACHE_TAG_LINE_ADDR_WIDTH = CACHE_TAG_WIDTH - 1; /* 15 bits of data (tag entry size minus valid bit) */
 
parameter CACHE_TAG_ADDR_LOW = CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH;
parameter CACHE_TAG_ADDR_HIGH = CACHE_TAG_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH + CACHE_LINE_ADDR_WIDTH - 1;
 
// Tag fields
parameter CACHE_TAG_VALID_BIT = 15;
 
// 31 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
// |--------------| | | | | | | | | | | | | | | | |
// +--------------------+ +-------------------+ +-----------+
// Tag entry Line address Address
// (15-bits) (8-bits) within line
// (5-bits)
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
wire [CACHE_TAG_WIDTH-1:0] tag_data_out;
reg [CACHE_TAG_WIDTH-1:0] tag_data_in;
reg tag_wr;
 
wire [CACHE_LINE_ADDR_WIDTH-1:0] tag_entry;
wire [CACHE_DWIDTH-1:0] cache_address_rd;
 
reg [CACHE_DWIDTH-1:0] cache_address_wr;
reg [31:0] cache_data_w;
reg cache_wr;
 
reg [CACHE_LINE_SIZE_WIDTH-3:0] fetch_word;
 
reg [31:0] last_pc;
reg [31:0] miss_pc;
 
wire busy_o;
wire miss_o;
 
reg initial_fetch;
reg flush_req;
 
reg [31:0] mem_addr_o;
reg mem_rd_o;
reg mem_burst_o;
 
reg [CACHE_LINE_ADDR_WIDTH-1:0] flush_addr;
reg flush_wr;
 
reg read_while_busy;
 
// Current state
parameter STATE_CHECK = 0;
parameter STATE_FETCH = 1;
parameter STATE_WAIT = 2;
parameter STATE_WAIT2 = 3;
parameter STATE_FLUSH = 4;
reg [3:0] state;
 
assign tag_entry = (state != STATE_CHECK) ? miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] : pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
assign cache_address_rd = pc_i[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:2];
 
assign miss_o = (!tag_data_out[CACHE_TAG_VALID_BIT] || (last_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] != tag_data_out[14:0])) ? 1'b1: 1'b0;
 
wire valid_o = !miss_o && !busy_o;
 
//-----------------------------------------------------------------
// Control logic
//-----------------------------------------------------------------
reg [CACHE_LINE_SIZE_WIDTH-3:0] v_line_word;
 
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
mem_addr_o <= 32'h00000000;
mem_rd_o <= 1'b0;
mem_burst_o <= 1'b0;
tag_wr <= 1'b0;
cache_address_wr<= {CACHE_DWIDTH{1'b0}};
cache_data_w <= 32'h00000000;
cache_wr <= 1'b0;
miss_pc <= BOOT_VECTOR + `VECTOR_RESET;
last_pc <= 32'h00000000;
state <= STATE_CHECK;
initial_fetch <= 1'b1;
read_while_busy <= 1'b0;
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b0}};
flush_wr <= 1'b0;
flush_req <= 1'b0;
end
else
begin
if (mem_accept_i)
mem_rd_o <= 1'b0;
tag_wr <= 1'b0;
cache_wr <= 1'b0;
initial_fetch <= 1'b0;
flush_wr <= 1'b0;
last_pc <= pc_i;
// Latch invalidate request even if can't be actioned now...
if (invalidate_i)
flush_req <= 1'b1;
 
// New request whilst cache busy?
if (rd_i)
read_while_busy <= 1'b1;
 
case (state)
 
//-----------------------------------------
// CHECK - check cache for hit or miss
//-----------------------------------------
STATE_CHECK :
begin
// Cache flush request pending?
if (flush_req || invalidate_i)
begin
flush_req <= 1'b0;
flush_addr <= {CACHE_LINE_ADDR_WIDTH{1'b1}};
flush_wr <= 1'b1;
state <= STATE_FLUSH;
 
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache flush request");
`endif
end
// Cache miss (& new read request not pending)
else if ((miss_o && !initial_fetch) && !rd_i && !read_while_busy)
begin
read_while_busy <= 1'b0;
 
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
 
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache miss at 0x%x (last=%x, current=%x)", miss_pc, last_pc, pc_i);
`endif
// Start fetch from memory
mem_addr_o <= {miss_pc[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b1;
state <= STATE_FETCH;
// Update tag memory with this line's details
tag_data_in <= {1'b1, miss_pc[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
end
// Cache hit (or new read request)
else
begin
`ifdef CONF_CORE_DEBUG
$display("Fetch: Cache hit at PC=%x (current=%x)", last_pc, pc_i);
if (read_while_busy)
$display("Fetch: Read request whilst busy PC=%x (current=%x)", last_pc, pc_i);
`endif
 
// Store fetch PC
miss_pc <= pc_i;
state <= STATE_CHECK;
read_while_busy <= 1'b0;
end
end
//-----------------------------------------
// FETCH - Fetch row from memory
//-----------------------------------------
STATE_FETCH :
begin
// Data ready from memory?
if (mem_ack_i)
begin
// Write data into cache
cache_address_wr<= {miss_pc[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH], fetch_word};
cache_data_w <= mem_data_i;
cache_wr <= 1'b1;
// Line fetch complete?
if (fetch_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
begin
state <= STATE_WAIT;
end
// Fetch next word for line
else
begin
v_line_word = fetch_word + 1'b1;
fetch_word <= v_line_word;
mem_addr_o <= {mem_addr_o[31:CACHE_LINE_SIZE_WIDTH], v_line_word, 2'b00};
mem_rd_o <= 1'b1;
if (fetch_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1))
begin
mem_burst_o <= 1'b0;
end
end
end
end
//-----------------------------------------
// FLUSH - Invalidate tag memory
//-----------------------------------------
STATE_FLUSH :
begin
if (flush_addr == {CACHE_LINE_ADDR_WIDTH{1'b0}})
begin
// Fetch current PC line again
mem_addr_o <= {pc_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b1;
state <= STATE_FETCH;
// Update tag memory with this line's details
tag_data_in <= {1'b1, pc_i[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
tag_wr <= 1'b1;
 
// Start of line
fetch_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
 
// Clear pending reads whilst busy
read_while_busy <= 1'b0;
end
else
begin
flush_addr <= flush_addr - 1;
flush_wr <= 1'b1;
state <= STATE_FLUSH;
end
end
//-----------------------------------------
// WAIT - Wait cycle
//-----------------------------------------
STATE_WAIT :
begin
// Allow extra wait state to handle write & read collision
state <= STATE_WAIT2;
end
//-----------------------------------------
// WAIT2 - Wait cycle
//-----------------------------------------
STATE_WAIT2 :
begin
`ifdef CONF_CORE_DEBUG
$display("Fetch: Filled line containing PC=%x", miss_pc);
`endif
state <= STATE_CHECK;
end
default:
;
endcase
end
end
 
// Stall the CPU if cache state machine is not idle!
assign busy_o = (state == STATE_CHECK & ~read_while_busy) ? 1'b0 : 1'b1;
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
// Tag memory
altor32_ram_dp
#(
.WIDTH(CACHE_TAG_WIDTH),
.SIZE(CACHE_LINE_ADDR_WIDTH)
)
u1_tag_mem
(
.aclk_i(clk_i),
.adat_o(tag_data_out),
.adat_i(tag_data_in),
.aadr_i(tag_entry),
.awr_i(tag_wr),
.bclk_i(clk_i),
.badr_i(flush_addr),
.bdat_o(/*open*/),
.bdat_i({CACHE_TAG_WIDTH{1'b0}}),
.bwr_i(flush_wr)
);
// Data memory
altor32_ram_dp
#(
.WIDTH(32),
.SIZE(CACHE_DWIDTH)
)
u2_data_mem
(
.aclk_i(clk_i),
.aadr_i(cache_address_rd),
.adat_o(instruction_o),
.adat_i(32'h00),
.awr_i(1'b0),
.bclk_i(clk_i),
.badr_i(cache_address_wr),
.bdat_o(/*open*/),
.bdat_i(cache_data_w),
.bwr_i(cache_wr)
);
 
endmodule
 
/rtl/cpu/altor32_regfile_alt.v
0,0 → 1,195
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Altera LPM register file
//-----------------------------------------------------------------
module altor32_regfile_alt
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output [31:0] reg_rs_o /*verilator public*/,
output [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter SUPPORT_32REGS = "ENABLED";
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg clk_delayed;
wire [31:0] data_out1;
wire [31:0] data_out2;
reg write_enable;
 
reg [31:0] reg_rs_o;
reg [31:0] reg_rt_o;
 
reg [4:0] addr_reg;
reg [31:0] data_reg;
 
wire [31:0] q1;
wire [31:0] q2;
 
//-----------------------------------------------------------------
// Async Read Process
//-----------------------------------------------------------------
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i)
begin
// Read Rs
if (rs_i == 5'b00000)
reg_rs_o <= 32'h00000000;
else
reg_rs_o <= data_out1;
 
// Read Rt
if (rt_i == 5'b00000)
reg_rt_o <= 32'h00000000;
else
reg_rt_o <= data_out2;
 
// Write enabled?
if ((rd_i != 5'b00000) & (wr_i == 1'b1))
write_enable <= 1'b1;
else
write_enable <= 1'b0;
end
 
//-----------------------------------------------------------------
// Sync addr & data
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i)
begin
addr_reg <= 5'b00000;
data_reg <= 32'h00000000;
 
end
else
begin
addr_reg <= rd_i;
data_reg <= reg_rd_i;
end
end
 
//-----------------------------------------------------------------
// Register File (using lpm_ram_dp)
// Unfortunatly, LPM_RAM_DP primitives have synchronous read ports.
// As this core requires asynchronous/non-registered read ports,
// we have to invert the readclock edge to get close to what we
// require.
// This will have negative timing implications!
//-----------------------------------------------------------------
lpm_ram_dp
#(
.lpm_width(32),
.lpm_widthad(5),
.lpm_indata("REGISTERED"),
.lpm_outdata("UNREGISTERED"),
.lpm_rdaddress_control("REGISTERED"),
.lpm_wraddress_control("REGISTERED"),
.lpm_file("UNUSED"),
.lpm_type("lpm_ram_dp"),
.lpm_hint("UNUSED")
)
lpm1
(
.rdclock(clk_delayed),
.rdclken(1'b1),
.rdaddress(rs_i),
.rden(1'b1),
.data(reg_rd_i),
.wraddress(rd_i),
.wren(write_enable),
.wrclock(clk_i),
.wrclken(1'b1),
.q(q1)
);
 
 
lpm_ram_dp
#(
.lpm_width(32),
.lpm_widthad(5),
.lpm_indata("REGISTERED"),
.lpm_outdata("UNREGISTERED"),
.lpm_rdaddress_control("REGISTERED"),
.lpm_wraddress_control("REGISTERED"),
.lpm_file("UNUSED"),
.lpm_type("lpm_ram_dp"),
.lpm_hint("UNUSED")
)
lpm2
(
.rdclock(clk_delayed),
.rdclken(1'b1),
.rdaddress(rt_i),
.rden(1'b1),
.data(reg_rd_i),
.wraddress(rd_i),
.wren(write_enable),
.wrclock(clk_i),
.wrclken(1'b1),
.q(q2)
);
 
//-----------------------------------------------------------------
// Combinatorial Assignments
//-----------------------------------------------------------------
 
// Delayed clock
assign clk_delayed = !clk_i;
 
// Reads are bypassed during write-back
assign data_out1 = (rs_i != addr_reg) ? q1 : data_reg;
assign data_out2 = (rt_i != addr_reg) ? q2 : data_reg;
 
endmodule
/rtl/cpu/altor32_dfu.v
0,0 → 1,206
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module: Data Forwarding Unit
//-----------------------------------------------------------------
module altor32_dfu
(
// Input registers
input [4:0] ra_i /*verilator public*/,
input [4:0] rb_i /*verilator public*/,
 
// Input register contents
input [31:0] ra_regval_i /*verilator public*/,
input [31:0] rb_regval_i /*verilator public*/,
 
// Dest register (EXEC stage)
input [4:0] rd_ex_i/*verilator public*/,
 
// Dest register (WB stage)
input [4:0] rd_wb_i/*verilator public*/,
 
// Load pending / target
input load_pending_i /*verilator public*/,
input [4:0] rd_load_i /*verilator public*/,
 
// Multiplier status
input mult_lo_ex_i /*verilator public*/,
input mult_hi_ex_i /*verilator public*/,
input mult_lo_wb_i /*verilator public*/,
input mult_hi_wb_i /*verilator public*/,
 
// Multiplier result
input [63:0] result_mult_i /*verilator public*/,
 
// Result (EXEC)
input [31:0] result_ex_i /*verilator public*/,
 
// Result (WB)
input [31:0] result_wb_i /*verilator public*/,
 
// Resolved register values
output reg [31:0] result_ra_o /*verilator public*/,
output reg [31:0] result_rb_o /*verilator public*/,
 
// Stall due to failed resolve
output reg stall_o /*verilator public*/
);
 
//-------------------------------------------------------------------
// Data forwarding unit
//-------------------------------------------------------------------
always @ *
begin
// Default to no forwarding
result_ra_o = ra_regval_i;
result_rb_o = rb_regval_i;
stall_o = 1'b0;
 
//---------------------------------------------------------------
// RA - Hazard detection & forwarding
//---------------------------------------------------------------
 
// Register[ra] hazard detection & forwarding logic
// (higher priority = latest results!)
if (ra_i != 5'b00000)
begin
//---------------------------------------------------------------
// RA from load (result not ready)
//---------------------------------------------------------------
if (ra_i == rd_load_i & load_pending_i)
begin
stall_o = 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" rA[%d] not ready as load still pending", ra_i);
`endif
end
//---------------------------------------------------------------
// RA from PC-4 (exec)
//---------------------------------------------------------------
else if (ra_i == rd_ex_i)
begin
// Multiplier has one cycle latency, stall if needed now
if (mult_lo_ex_i | mult_hi_wb_i)
stall_o = 1'b1;
else
begin
result_ra_o = result_ex_i;
`ifdef CONF_CORE_DEBUG
$display(" rA[%d] forwarded 0x%08x (PC-4)", ra_i, result_ra_o);
`endif
end
end
//---------------------------------------------------------------
// RA from PC-8 (writeback)
//---------------------------------------------------------------
else if (ra_i == rd_wb_i)
begin
if (mult_hi_wb_i)
result_ra_o = result_mult_i[63:32];
else if (mult_lo_wb_i)
result_ra_o = result_mult_i[31:0];
else
result_ra_o = result_wb_i;
 
`ifdef CONF_CORE_DEBUG
$display(" rA[%d] forwarded 0x%08x (PC-8)", ra_i, result_ra_o);
`endif
end
end
//---------------------------------------------------------------
// RB - Hazard detection & forwarding
//---------------------------------------------------------------
 
// Register[rb] hazard detection & forwarding logic
// (higher priority = latest results!)
if (rb_i != 5'b00000)
begin
 
//---------------------------------------------------------------
// RB from load (result not ready)
//---------------------------------------------------------------
if (rb_i == rd_load_i & load_pending_i)
begin
stall_o = 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" rB[%d] not ready as load still pending", rb_i);
`endif
end
//---------------------------------------------------------------
// RB from PC-4 (exec)
//---------------------------------------------------------------
else if (rb_i == rd_ex_i)
begin
// Multiplier has one cycle latency, stall if needed now
if (mult_lo_ex_i | mult_hi_wb_i)
stall_o = 1'b1;
else
begin
result_rb_o = result_ex_i;
 
`ifdef CONF_CORE_DEBUG
$display(" rB[%d] forwarded 0x%08x (PC-4)", rb_i, result_rb_o);
`endif
end
end
//---------------------------------------------------------------
// RB from PC-8 (writeback)
//---------------------------------------------------------------
else if (rb_i == rd_wb_i)
begin
if (mult_hi_wb_i)
result_rb_o = result_mult_i[63:32];
else if (mult_lo_wb_i)
result_rb_o = result_mult_i[31:0];
else
result_rb_o = result_wb_i;
 
`ifdef CONF_CORE_DEBUG
$display(" rB[%d] forwarded 0x%08x (PC-8)", rb_i, result_rb_o);
`endif
end
end
end
 
endmodule
/rtl/cpu/altor32_funcs.v
0,0 → 1,253
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// less_than_signed: Less than operator (signed)
// Inputs: x = left operand, y = right operand
// Return: (int)x < (int)y
//-----------------------------------------------------------------
function [0:0] less_than_signed;
input [31:0] x;
input [31:0] y;
reg [31:0] v;
begin
v = (x - y);
if (x[31] != y[31])
less_than_signed = x[31];
else
less_than_signed = v[31];
end
endfunction
 
//-----------------------------------------------------------------
// less_than_equal_signed: Less than or equal to operator (signed)
// Inputs: x = left operand, y = right operand
// Return: (int)x <= (int)y
//-----------------------------------------------------------------
function [0:0] less_than_equal_signed;
input [31:0] x;
input [31:0] y;
reg [31:0] v;
begin
v = (x - y);
if (x == y)
less_than_equal_signed = 1'b1;
else if (x[31] != y[31])
less_than_equal_signed = x[31];
else
less_than_equal_signed = v[31];
end
endfunction
 
//-----------------------------------------------------------------
// greater_than_signed: Greater than operator (signed)
// Inputs: x = left operand, y = right operand
// Return: (int)x > (int)y
//-----------------------------------------------------------------
function [0:0] greater_than_signed;
input [31:0] x;
input [31:0] y;
reg [31:0] v;
begin
v = (y - x);
if (x[31] != y[31])
greater_than_signed = y[31];
else
greater_than_signed = v[31];
end
endfunction
 
//-----------------------------------------------------------------
// greater_than_equal_signed: Greater than or equal to operator (signed)
// Inputs: x = left operand, y = right operand
// Return: (int)x >= (int)y
//-----------------------------------------------------------------
function [0:0] greater_than_equal_signed;
input [31:0] x;
input [31:0] y;
reg [31:0] v;
begin
v = (y - x);
if (x == y)
greater_than_equal_signed = 1'b1;
else if (x[31] != y[31])
greater_than_equal_signed = y[31];
else
greater_than_equal_signed = v[31];
end
endfunction
 
//-----------------------------------------------------------------
// sign_extend_imm16: Extend 16-bit signed value to 32-bit signed.
// Inputs: x = operand
// Return: (int)((short)x)
//-----------------------------------------------------------------
function [31:0] sign_extend_imm16;
input [15:0] x;
reg [31:0] y;
begin
if (x[15] == 1'b0)
y[31:16] = 16'b0000000000000000;
else
y[31:16] = 16'b1111111111111111;
 
y[15:0] = x;
sign_extend_imm16 = y;
end
endfunction
 
//-----------------------------------------------------------------
// sign_extend_imm26: Extend 26-bit signed value to 32-bit signed.
// Inputs: x = operand
// Return: (int)((short)x)
//-----------------------------------------------------------------
function [31:0] sign_extend_imm26;
input [25:0] x;
reg [31:0] y;
begin
if (x[25] == 1'b0)
y[31:26] = 6'b000000;
else
y[31:26] = 6'b111111;
 
y[25:0] = x;
sign_extend_imm26 = y;
end
endfunction
 
//-----------------------------------------------------------------
// extend_imm16: Extend 16-bit unsigned value to 32-bit unsigned.
// Inputs: x = operand
// Return: (unsigned int)x
//-----------------------------------------------------------------
function [31:0] extend_imm16;
input [15:0] x;
begin
extend_imm16 = {16'h0000,x};
end
endfunction
 
//-----------------------------------------------------------------
// less_than_zero: Is signed value less than 0?
// Inputs: x = operand
// Return: ((int)x) < 0
//-----------------------------------------------------------------
function [0:0] less_than_zero;
input [31:0] x;
begin
if ((x != 32'h00000000) & (x[31] == 1'b1))
less_than_zero = 1'b1;
else
less_than_zero = 1'b0;
end
endfunction
 
//-----------------------------------------------------------------
// less_than_equal_zero: Is signed value less than or equal to 0?
// Inputs: x = operand
// Return: ((int)x) <= 0
//-----------------------------------------------------------------
function [0:0] less_than_equal_zero;
input [31:0] x;
begin
if ((x == 32'h00000000) | (x[31] == 1'b1))
less_than_equal_zero = 1'b1;
else
less_than_equal_zero = 1'b0;
end
endfunction
 
//-----------------------------------------------------------------
// more_than_equal_zero: Is signed value more than or equal to 0?
// Inputs: x = operand
// Return: ((int)x) >= 0
//-----------------------------------------------------------------
function [0:0] more_than_equal_zero;
input [31:0] x;
begin
if ((x == 32'h00000000) | (x[31] == 1'b0))
more_than_equal_zero = 1'b1;
else
more_than_equal_zero = 1'b0;
end
endfunction
 
//-----------------------------------------------------------------
// more_than_equal_zero: Is signed value more than 0?
// Inputs: x = operand
// Return: ((int)x) > 0
//-----------------------------------------------------------------
function [0:0] more_than_zero;
input [31:0] x;
begin
if (((x != 32'h00000000) & (x[31] == 1'b0)))
more_than_zero = 1'b1;
else
more_than_zero = 1'b0;
end
endfunction
 
//-----------------------------------------------------------------
// is_load_operation: Is this opcode a load operation?
// Inputs: opcode
// Return: 1 or 0
//-----------------------------------------------------------------
function [0:0] is_load_operation;
input [7:0] opcode;
begin
is_load_operation = (opcode == `INST_OR32_LBS ||
opcode == `INST_OR32_LBZ ||
opcode == `INST_OR32_LHS ||
opcode == `INST_OR32_LHZ ||
opcode == `INST_OR32_LWZ ||
opcode == `INST_OR32_LWS) ? 1'b1 : 1'b0;
end
endfunction
 
//-----------------------------------------------------------------
// is_store_operation: Is this opcode a store operation?
// Inputs: opcode
// Return: 1 or 0
//-----------------------------------------------------------------
function [0:0] is_store_operation;
input [7:0] opcode;
begin
is_store_operation = (opcode == `INST_OR32_SB ||
opcode == `INST_OR32_SH ||
opcode == `INST_OR32_SW) ? 1'b1 : 1'b0;
end
endfunction
/rtl/cpu/altor32.v
0,0 → 1,475
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - AltOR32 CPU
//-----------------------------------------------------------------
module cpu
(
// General
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
input intr_i /*verilator public*/,
input nmi_i /*verilator public*/,
output fault_o /*verilator public*/,
output break_o /*verilator public*/,
 
// Instruction memory
output [31:0] imem_addr_o /*verilator public*/,
output imem_rd_o /*verilator public*/,
output imem_burst_o /*verilator public*/,
input [31:0] imem_data_in_i /*verilator public*/,
input imem_accept_i /*verilator public*/,
input imem_ack_i /*verilator public*/,
 
// Data memory
output [31:0] dmem_addr_o /*verilator public*/,
output [31:0] dmem_data_out_o /*verilator public*/,
input [31:0] dmem_data_in_i /*verilator public*/,
output [3:0] dmem_wr_o /*verilator public*/,
output dmem_rd_o /*verilator public*/,
output dmem_burst_o /*verilator public*/,
input dmem_accept_i /*verilator public*/,
input dmem_ack_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
parameter ISR_VECTOR = 32'h00000000;
parameter REGISTER_FILE_TYPE = "SIMULATION";
parameter ENABLE_ICACHE = "ENABLED";
parameter ENABLE_DCACHE = "DISABLED";
parameter SUPPORT_32REGS = "ENABLED";
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
// Register number (rA)
wire [4:0] w_ra;
 
// Register number (rB)
wire [4:0] w_rb;
 
// Destination register number (pre execute stage)
wire [4:0] w_rd;
 
// Destination register number (post execute stage)
wire [4:0] w_e_rd;
 
// Register value (rA)
wire [31:0] w_reg_ra;
 
// Register value (rB)
wire [31:0] w_reg_rb;
 
// Current opcode
wire [31:0] w_d_opcode;
wire [31:0] w_d_pc;
wire w_d_valid;
 
wire [31:0] w_e_opcode;
 
// Register writeback value
wire [4:0] w_wb_rd;
wire [31:0] w_wb_reg_rd;
 
// Register writeback enable
wire w_wb_write_rd;
 
// Result from execute
wire [31:0] w_e_result;
wire w_e_mult;
wire [31:0] w_e_mult_result;
 
// Branch request
wire w_e_branch;
wire [31:0] w_e_branch_pc;
wire w_e_stall;
 
wire icache_rd;
wire [31:0] icache_pc;
wire [31:0] icache_inst;
wire icache_miss;
wire icache_valid;
wire icache_busy;
wire icache_invalidate;
 
wire [31:0] dcache_addr;
wire [31:0] dcache_data_o;
wire [31:0] dcache_data_i;
wire [3:0] dcache_wr;
wire dcache_rd;
wire dcache_ack;
wire dcache_accept;
wire dcache_flush;
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
 
// Instruction Cache
generate
if (ENABLE_ICACHE == "ENABLED")
begin : ICACHE
// Instruction cache
altor32_icache
#(
.BOOT_VECTOR(BOOT_VECTOR)
)
u_icache
(
.clk_i(clk_i),
.rst_i(rst_i),
// Processor interface
.rd_i(icache_rd),
.pc_i(icache_pc),
.instruction_o(icache_inst),
.valid_o(icache_valid),
.invalidate_i(icache_invalidate),
// Status
.miss_o(icache_miss),
.busy_o(icache_busy),
// Instruction memory
.mem_addr_o(imem_addr_o),
.mem_data_i(imem_data_in_i),
.mem_burst_o(imem_burst_o),
.mem_rd_o(imem_rd_o),
.mem_accept_i(imem_accept_i),
.mem_ack_i(imem_ack_i)
);
end
else
begin
// No instruction cache
altor32_noicache
u_icache
(
.clk_i(clk_i),
.rst_i(rst_i),
// Processor interface
.rd_i(icache_rd),
.pc_i(icache_pc),
.instruction_o(icache_inst),
.valid_o(icache_valid),
// Instruction memory
.mem_addr_o(imem_addr_o),
.mem_data_i(imem_data_in_i),
.mem_burst_o(imem_burst_o),
.mem_rd_o(imem_rd_o),
.mem_accept_i(imem_accept_i),
.mem_ack_i(imem_ack_i)
);
end
endgenerate
 
// Instruction Fetch
altor32_fetch
#(
.BOOT_VECTOR(BOOT_VECTOR)
)
u_fetch
(
// General
.clk_i(clk_i),
.rst_i(rst_i),
// Instruction memory
.pc_o(icache_pc),
.data_i(icache_inst),
.fetch_o(icache_rd),
.data_valid_i(icache_valid),
// Fetched opcode
.opcode_o(w_d_opcode),
.opcode_pc_o(w_d_pc),
.opcode_valid_o(w_d_valid),
// Branch target
.branch_i(w_e_branch),
.branch_pc_i(w_e_branch_pc),
.stall_i(w_e_stall),
 
// Decoded register details
.ra_o(w_ra),
.rb_o(w_rb),
.rd_o(w_rd)
);
 
// Register file
generate
if (REGISTER_FILE_TYPE == "XILINX")
begin
altor32_regfile_xil
#(
.SUPPORT_32REGS(SUPPORT_32REGS)
)
reg_bank
(
// Clocking
.clk_i(clk_i),
.rst_i(rst_i),
.wr_i(w_wb_write_rd),
 
// Tri-port
.rs_i(w_ra),
.rt_i(w_rb),
.rd_i(w_wb_rd),
.reg_rs_o(w_reg_ra),
.reg_rt_o(w_reg_rb),
.reg_rd_i(w_wb_reg_rd)
);
end
else if (REGISTER_FILE_TYPE == "ALTERA")
begin
altor32_regfile_alt
#(
.SUPPORT_32REGS(SUPPORT_32REGS)
)
reg_bank
(
// Clocking
.clk_i(clk_i),
.rst_i(rst_i),
.wr_i(w_wb_write_rd),
 
// Tri-port
.rs_i(w_ra),
.rt_i(w_rb),
.rd_i(w_wb_rd),
.reg_rs_o(w_reg_ra),
.reg_rt_o(w_reg_rb),
.reg_rd_i(w_wb_reg_rd)
);
end
else
begin
altor32_regfile_sim
#(
.SUPPORT_32REGS(SUPPORT_32REGS)
)
reg_bank
(
// Clocking
.clk_i(clk_i),
.rst_i(rst_i),
.wr_i(w_wb_write_rd),
 
// Tri-port
.rs_i(w_ra),
.rt_i(w_rb),
.rd_i(w_wb_rd),
.reg_rs_o(w_reg_ra),
.reg_rt_o(w_reg_rb),
.reg_rd_i(w_wb_reg_rd)
);
end
endgenerate
 
generate
if (ENABLE_DCACHE == "ENABLED")
begin
// Data cache
altor32_dcache
u_dcache
(
.clk_i(clk_i),
.rst_i(rst_i),
 
.flush_i(dcache_flush),
// Processor interface
.address_i({dcache_addr[31:2], 2'b00}),
.data_o(dcache_data_i),
.data_i(dcache_data_o),
.wr_i(dcache_wr),
.rd_i(dcache_rd),
.accept_o(dcache_accept),
.ack_o(dcache_ack),
// Memory interface (slave)
.mem_addr_o(dmem_addr_o),
.mem_data_i(dmem_data_in_i),
.mem_data_o(dmem_data_out_o),
.mem_burst_o(dmem_burst_o),
.mem_rd_o(dmem_rd_o),
.mem_wr_o(dmem_wr_o),
.mem_accept_i(dmem_accept_i),
.mem_ack_i(dmem_ack_i)
);
end
else
begin
 
// No data cache
assign dmem_addr_o = {dcache_addr[31:2], 2'b00};
assign dmem_data_out_o = dcache_data_o;
assign dcache_data_i = dmem_data_in_i;
assign dmem_rd_o = dcache_rd;
assign dmem_wr_o = dcache_wr;
assign dmem_burst_o = 1'b0;
assign dcache_ack = dmem_ack_i;
assign dcache_accept = dmem_accept_i;
end
endgenerate
 
// Execution unit
altor32_exec
#(
.BOOT_VECTOR(BOOT_VECTOR),
.ISR_VECTOR(ISR_VECTOR)
)
u_exec
(
// General
.clk_i(clk_i),
.rst_i(rst_i),
 
.intr_i(intr_i),
.nmi_i(nmi_i),
// Status
.fault_o(fault_o),
.break_o(break_o),
// Cache control
.icache_flush_o(icache_invalidate),
.dcache_flush_o(dcache_flush),
// Branch target
.branch_o(w_e_branch),
.branch_pc_o(w_e_branch_pc),
.stall_o(w_e_stall),
 
// Opcode & arguments
.opcode_i(w_d_opcode),
.opcode_pc_i(w_d_pc),
.opcode_valid_i(w_d_valid),
 
.reg_ra_i(w_ra),
.reg_ra_value_i(w_reg_ra),
 
.reg_rb_i(w_rb),
.reg_rb_value_i(w_reg_rb),
.reg_rd_i(w_rd),
 
// Output
.opcode_o(w_e_opcode),
.reg_rd_o(w_e_rd),
.reg_rd_value_o(w_e_result),
.mult_o(w_e_mult),
.mult_res_o(w_e_mult_result),
 
// Register write back bypass
.wb_rd_i(w_wb_rd),
.wb_rd_value_i(w_wb_reg_rd),
 
// Memory Interface
.dmem_addr_o(dcache_addr),
.dmem_data_out_o(dcache_data_o),
.dmem_data_in_i(dcache_data_i),
.dmem_wr_o(dcache_wr),
.dmem_rd_o(dcache_rd),
.dmem_accept_i(dcache_accept),
.dmem_ack_i(dcache_ack)
);
 
// Register file writeback
altor32_writeback
u_wb
(
// General
.clk_i(clk_i),
.rst_i(rst_i),
 
// Opcode
.opcode_i(w_e_opcode),
 
// Register target
.rd_i(w_e_rd),
// ALU result
.alu_result_i(w_e_result),
 
// Memory load result
.mem_result_i(dcache_data_i),
.mem_offset_i(dcache_addr[1:0]),
.mem_ready_i(dcache_ack),
 
// Multiplier result
.mult_i(w_e_mult),
.mult_result_i(w_e_mult_result),
 
// Outputs
.write_enable_o(w_wb_write_rd),
.write_addr_o(w_wb_rd),
.write_data_o(w_wb_reg_rd)
);
 
//-------------------------------------------------------------------
// Hooks for debug
//-------------------------------------------------------------------
`ifdef verilator
function [31:0] get_pc;
// verilator public
get_pc = w_d_pc;
endfunction
function get_fault;
// verilator public
get_fault = fault_o;
endfunction
function get_break;
// verilator public
get_break = break_o;
endfunction
`endif
 
endmodule
/rtl/cpu/altor32_alu.v
0,0 → 1,209
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - ALU
//-----------------------------------------------------------------
module altor32_alu
(
// ALU operation select
input [3:0] op_i /*verilator public*/,
 
// Operands
input [31:0] a_i /*verilator public*/,
input [31:0] b_i /*verilator public*/,
input c_i /*verilator public*/,
 
// Result
output [31:0] p_o /*verilator public*/,
 
// Carry
output reg c_o /*verilator public*/,
output reg c_update_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [31:0] result;
 
reg [31:16] shift_right_fill;
reg [31:0] shift_right_1;
reg [31:0] shift_right_2;
reg [31:0] shift_right_4;
reg [31:0] shift_right_8;
 
reg [31:0] shift_left_1;
reg [31:0] shift_left_2;
reg [31:0] shift_left_4;
reg [31:0] shift_left_8;
 
//-----------------------------------------------------------------
// ALU
//-----------------------------------------------------------------
always @ (op_i or a_i or b_i or c_i)
begin
case (op_i)
//----------------------------------------------
// Shift Left
//----------------------------------------------
`ALU_SHIFTL :
begin
if (b_i[0] == 1'b1)
shift_left_1 = {a_i[30:0],1'b0};
else
shift_left_1 = a_i;
 
if (b_i[1] == 1'b1)
shift_left_2 = {shift_left_1[29:0],2'b00};
else
shift_left_2 = shift_left_1;
 
if (b_i[2] == 1'b1)
shift_left_4 = {shift_left_2[27:0],4'b0000};
else
shift_left_4 = shift_left_2;
 
if (b_i[3] == 1'b1)
shift_left_8 = {shift_left_4[23:0],8'b00000000};
else
shift_left_8 = shift_left_4;
 
if (b_i[4] == 1'b1)
result = {shift_left_8[15:0],16'b0000000000000000};
else
result = shift_left_8;
 
c_o = 1'b0;
c_update_o = 1'b0;
end
//----------------------------------------------
// Shift Right
//----------------------------------------------
`ALU_SHIFTR, `ALU_SHIRTR_ARITH:
begin
// Arithmetic shift? Fill with 1's if MSB set
if (a_i[31] == 1'b1 && op_i == `ALU_SHIRTR_ARITH)
shift_right_fill = 16'b1111111111111111;
else
shift_right_fill = 16'b0000000000000000;
 
if (b_i[0] == 1'b1)
shift_right_1 = {shift_right_fill[31], a_i[31:1]};
else
shift_right_1 = a_i;
 
if (b_i[1] == 1'b1)
shift_right_2 = {shift_right_fill[31:30], shift_right_1[31:2]};
else
shift_right_2 = shift_right_1;
 
if (b_i[2] == 1'b1)
shift_right_4 = {shift_right_fill[31:28], shift_right_2[31:4]};
else
shift_right_4 = shift_right_2;
 
if (b_i[3] == 1'b1)
shift_right_8 = {shift_right_fill[31:24], shift_right_4[31:8]};
else
shift_right_8 = shift_right_4;
 
if (b_i[4] == 1'b1)
result = {shift_right_fill[31:16], shift_right_8[31:16]};
else
result = shift_right_8;
 
c_o = 1'b0;
c_update_o = 1'b0;
end
//----------------------------------------------
// Arithmetic
//----------------------------------------------
`ALU_ADD :
begin
{c_o, result} = (a_i + b_i);
c_update_o = 1'b1;
end
`ALU_ADDC :
begin
{c_o, result} = (a_i + b_i) + {31'h00000000, c_i};
c_update_o = 1'b1;
end
`ALU_SUB :
begin
result = (a_i - b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
//----------------------------------------------
// Logical
//----------------------------------------------
`ALU_AND :
begin
result = (a_i & b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
`ALU_OR :
begin
result = (a_i | b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
`ALU_XOR :
begin
result = (a_i ^ b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
default :
begin
result = a_i;
c_o = 1'b0;
c_update_o = 1'b0;
end
endcase
end
 
assign p_o = result;
 
endmodule
/rtl/cpu/altor32_ram_sp.v
0,0 → 1,77
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: altor32_ram_sp - Single port RAM (used in cache)
//-----------------------------------------------------------------
module altor32_ram_sp
(
input clk_i /*verilator public*/,
output [(WIDTH - 1):0] dat_o /*verilator public*/,
input [(WIDTH - 1):0] dat_i /*verilator public*/,
input [(SIZE - 1):0] adr_i /*verilator public*/,
input wr_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] WIDTH = 8;
parameter [31:0] SIZE = 14;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/;
reg [(SIZE - 1):0] rd_addr;
 
//-----------------------------------------------------------------
// Processes
//-----------------------------------------------------------------
always @ (posedge clk_i)
begin
if (wr_i == 1'b1)
ram[adr_i] <= dat_i;
rd_addr <= adr_i;
end
 
//-------------------------------------------------------------------
// Combinatorial
//-------------------------------------------------------------------
assign dat_o = ram[rd_addr];
 
endmodule
/rtl/cpu/altor32_defs.v
0,0 → 1,185
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// ALU Operations
//-----------------------------------------------------------------
`define ALU_NONE 4'b0000
`define ALU_SHIFTL 4'b0001
`define ALU_SHIFTR 4'b0010
`define ALU_SHIRTR_ARITH 4'b0011
`define ALU_ADD 4'b0100
`define ALU_ADDC 4'b0101
`define ALU_SUB 4'b0110
`define ALU_AND 4'b0111
`define ALU_OR 4'b1000
`define ALU_XOR 4'b1001
 
//-----------------------------------------------------------------
// ALU Instructions
//-----------------------------------------------------------------
`define INST_OR32_ALU 8'h38
`define INST_OR32_ADD 8'h00
`define INST_OR32_ADDC 8'h01
`define INST_OR32_AND 8'h03
`define INST_OR32_OR 8'h04
`define INST_OR32_SLL 8'h08
`define INST_OR32_SRA 8'h28
`define INST_OR32_SRL 8'h18
`define INST_OR32_SUB 8'h02
`define INST_OR32_XOR 8'h05
`define INST_OR32_MUL 8'hc6
`define INST_OR32_MULU 8'hcb
 
//-----------------------------------------------------------------
// INST_OR32_SHIFTI Instructions
//-----------------------------------------------------------------
`define INST_OR32_SHIFTI 8'h2E
`define INST_OR32_SLLI 2'b00
`define INST_OR32_SRAI 2'b10
`define INST_OR32_SRLI 2'b01
 
//-----------------------------------------------------------------
// General Instructions
//-----------------------------------------------------------------
`define INST_OR32_ADDI 8'h27
`define INST_OR32_ANDI 8'h29
`define INST_OR32_BF 8'h04
`define INST_OR32_BNF 8'h03
`define INST_OR32_J 8'h00
`define INST_OR32_JAL 8'h01
`define INST_OR32_JALR 8'h12
`define INST_OR32_JR 8'h11
`define INST_OR32_MFSPR 8'h2D
`define INST_OR32_MOVHI 8'h06
`define INST_OR32_MTSPR 8'h30
`define INST_OR32_NOP 8'h05
`define INST_OR32_ORI 8'h2A
`define INST_OR32_RFE 8'h09
`define INST_OR32_SB 8'h36
`define INST_OR32_SH 8'h37
`define INST_OR32_SW 8'h35
`define INST_OR32_XORI 8'h2B
`define INST_OR32_LBS 8'h24
`define INST_OR32_LBZ 8'h23
`define INST_OR32_LHS 8'h26
`define INST_OR32_LHZ 8'h25
`define INST_OR32_LWZ 8'h21
`define INST_OR32_LWS 8'h22
 
//-----------------------------------------------------------------
// Set Flag Instructions
//-----------------------------------------------------------------
`define INST_OR32_SFXX 8'h2F
`define INST_OR32_SFXXI 8'h39
`define INST_OR32_SFEQ 16'h0720
`define INST_OR32_SFEQI 16'h05E0
`define INST_OR32_SFGES 16'h072B
`define INST_OR32_SFGESI 16'h05EB
`define INST_OR32_SFGEU 16'h0723
`define INST_OR32_SFGEUI 16'h05E3
`define INST_OR32_SFGTS 16'h072A
`define INST_OR32_SFGTSI 16'h05EA
`define INST_OR32_SFGTU 16'h0722
`define INST_OR32_SFGTUI 16'h05E2
`define INST_OR32_SFLES 16'h072D
`define INST_OR32_SFLESI 16'h05ED
`define INST_OR32_SFLEU 16'h0725
`define INST_OR32_SFLEUI 16'h05E5
`define INST_OR32_SFLTS 16'h072C
`define INST_OR32_SFLTSI 16'h05EC
`define INST_OR32_SFLTU 16'h0724
`define INST_OR32_SFLTUI 16'h05E4
`define INST_OR32_SFNE 16'h0721
`define INST_OR32_SFNEI 16'h05E1
 
//-----------------------------------------------------------------
// Misc Instructions
//-----------------------------------------------------------------
`define INST_OR32_MISC 8'h08
`define INST_OR32_SYS 8'h20
`define INST_OR32_TRAP 8'h21
 
`define INST_OR32_BUBBLE 8'h3F
`define OPCODE_INST_BUBBLE 32'hFC000000
 
//-----------------------------------------------------------------
// SPR Register Map
//-----------------------------------------------------------------
`define SPR_REG_VR 16'h0000
`define SPR_VERSION_CURRENT 8'h00
`define SPR_REG_SR 16'h0011
`define SPR_REG_EPCR 16'h0020
`define SPR_REG_ESR 16'h0040
 
`define SPR_REG_MACLO 16'h0080
`define SPR_REG_MACHI 16'h0081
 
//-----------------------------------------------------------------
// SR Register bits
//-----------------------------------------------------------------
`define OR32_SR_SM 0
`define OR32_SR_TEE 1
`define OR32_SR_IEE 2
`define OR32_SR_DCE 3
`define OR32_SR_ICE 4
`define OR32_SR_DME 5
`define OR32_SR_IME 6
`define OR32_SR_LEE 7
`define OR32_SR_CE 8
`define OR32_SR_F 9
`define OR32_SR_CY 10
`define OR32_SR_OV 11
`define OR32_SR_OVE 12
`define OR32_SR_DSX 13
`define OR32_SR_EPH 14
`define OR32_SR_FO 15
`define OR32_SR_TED 16
`define OR32_SR_ICACHE_FLUSH 17
`define OR32_SR_DCACHE_FLUSH 18
 
//-----------------------------------------------------------------
// OR32 Vectors
// NOTE: These differ from the real OR32 vectors for space reasons
//-----------------------------------------------------------------
`define VECTOR_RESET 32'h00000100
`define VECTOR_ILLEGAL_INST 32'h00000200
`define VECTOR_EXTINT 32'h00000300
`define VECTOR_SYSCALL 32'h00000400
`define VECTOR_TRAP 32'h00000600
`define VECTOR_NMI 32'h00000700
`define VECTOR_BUS_ERROR 32'h00000800
/rtl/cpu/altor32_dcache_mem_if.v
0,0 → 1,311
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module - Data Cache Memory Interface
//-----------------------------------------------------------------
module altor32_dcache_mem_if
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
// Cache interface
input [31:0] address_i /*verilator public*/,
input [31:0] data_i /*verilator public*/,
output [31:0] data_o /*verilator public*/,
input fill_i /*verilator public*/,
input evict_i /*verilator public*/,
input [31:0] evict_addr_i /*verilator public*/,
input rd_single_i /*verilator public*/,
input [3:0] wr_single_i /*verilator public*/,
output done_o /*verilator public*/,
 
// Cache memory (fill/evict)
output [31:2] cache_addr_o /*verilator public*/,
output [31:0] cache_data_o /*verilator public*/,
input [31:0] cache_data_i /*verilator public*/,
output cache_wr_o /*verilator public*/,
// Memory interface (slave)
output [31:0] mem_addr_o /*verilator public*/,
input [31:0] mem_data_i /*verilator public*/,
output [31:0] mem_data_o /*verilator public*/,
output mem_burst_o /*verilator public*/,
output mem_rd_o /*verilator public*/,
output [3:0] mem_wr_o /*verilator public*/,
input mem_accept_i/*verilator public*/,
input mem_ack_i/*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
parameter CACHE_LINE_WORDS_IDX_MAX = CACHE_LINE_SIZE_WIDTH - 2; /* 3-bit -> 8 words */
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
 
reg [31:2] cache_addr_o;
reg [31:0] cache_data_o;
reg cache_wr_o;
reg [31:CACHE_LINE_SIZE_WIDTH] line_address;
reg [CACHE_LINE_SIZE_WIDTH-3:0] line_word;
 
reg [31:0] data_o;
reg done_o;
 
reg [31:0] mem_addr_o;
reg [31:0] mem_data_o;
reg mem_rd_o;
reg [3:0] mem_wr_o;
reg mem_burst_o;
 
// Current state
parameter STATE_IDLE = 0;
parameter STATE_FETCH = 1;
parameter STATE_READ_WAIT = 2;
parameter STATE_WRITE = 3;
parameter STATE_WRITE_WAIT = 4;
parameter STATE_READ_SINGLE = 5;
parameter STATE_WRITE_SINGLE= 6;
 
reg [3:0] state;
 
//-----------------------------------------------------------------
// Control logic
//-----------------------------------------------------------------
reg [CACHE_LINE_SIZE_WIDTH-3:0] v_line_word;
 
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
begin
line_address <= {32-CACHE_LINE_SIZE_WIDTH{1'b0}};
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
mem_addr_o <= 32'h00000000;
mem_data_o <= 32'h00000000;
mem_wr_o <= 4'h0;
mem_rd_o <= 1'b0;
mem_burst_o <= 1'b0;
cache_addr_o <= 30'h00000000;
cache_data_o <= 32'h00000000;
cache_wr_o <= 1'b0;
done_o <= 1'b0;
data_o <= 32'h00000000;
state <= STATE_IDLE;
end
else
begin
if (mem_accept_i)
begin
mem_rd_o <= 1'b0;
mem_wr_o <= 4'h0;
end
 
done_o <= 1'b0;
cache_wr_o <= 1'b0;
case (state)
 
//-----------------------------------------
// IDLE
//-----------------------------------------
STATE_IDLE :
begin
// Perform cache evict (write)
if (evict_i)
begin
line_address <= evict_addr_i[31:CACHE_LINE_SIZE_WIDTH];
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
 
// Read data from cache
cache_addr_o <= {evict_addr_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH-2{1'b0}}};
state <= STATE_READ_WAIT;
end
// Perform cache fill (read)
else if (fill_i)
begin
line_address <= address_i[31:CACHE_LINE_SIZE_WIDTH];
line_word <= {CACHE_LINE_SIZE_WIDTH-2{1'b0}};
// Start fetch from memory
mem_addr_o <= {address_i[31:CACHE_LINE_SIZE_WIDTH], {CACHE_LINE_SIZE_WIDTH{1'b0}}};
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b1;
state <= STATE_FETCH;
end
// Read single
else if (rd_single_i)
begin
// Start fetch from memory
mem_addr_o <= address_i;
mem_data_o <= 32'b0;
mem_rd_o <= 1'b1;
mem_burst_o <= 1'b0;
state <= STATE_READ_SINGLE;
end
// Write single
else if (|wr_single_i)
begin
// Start fetch from memory
mem_addr_o <= address_i;
mem_data_o <= data_i;
mem_wr_o <= wr_single_i;
mem_burst_o <= 1'b0;
state <= STATE_WRITE_SINGLE;
end
end
//-----------------------------------------
// FETCH - Fetch line from memory
//-----------------------------------------
STATE_FETCH :
begin
// Data ready from memory?
if (mem_ack_i && mem_rd_o == 1'b0)
begin
// Write data into cache
cache_addr_o <= {line_address, line_word};
cache_data_o <= mem_data_i;
cache_wr_o <= 1'b1;
// Line fetch complete?
if (line_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
begin
done_o <= 1'b1;
state <= STATE_IDLE;
end
// Fetch next word for line
else
begin
v_line_word = line_word + 1'b1;
line_word <= v_line_word;
mem_addr_o <= {line_address, v_line_word, 2'b00};
mem_rd_o <= 1'b1;
if (line_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1))
begin
mem_burst_o <= 1'b0;
end
end
end
end
//-----------------------------------------
// READ_WAIT - Wait for data from cache
//-----------------------------------------
STATE_READ_WAIT :
begin
// Not used yet, but set for start of burst
mem_burst_o <= 1'b1;
state <= STATE_WRITE;
end
//-----------------------------------------
// WRITE - Write word to memory
//-----------------------------------------
STATE_WRITE :
begin
// Write data into memory from cache
mem_addr_o <= {line_address, line_word, 2'b00};
mem_data_o <= cache_data_i;
mem_wr_o <= 4'b1111;
 
// Setup next word read from cache
v_line_word = line_word + 1'b1;
cache_addr_o <= {line_address, v_line_word};
 
state <= STATE_WRITE_WAIT;
end
//-----------------------------------------
// WRITE_WAIT - Wait for write to complete
//-----------------------------------------
STATE_WRITE_WAIT:
begin
// Write to memory complete
if (mem_ack_i && mem_wr_o == 4'b0)
begin
// Line write complete?
if (line_word == {CACHE_LINE_WORDS_IDX_MAX{1'b1}})
begin
done_o <= 1'b1;
state <= STATE_IDLE;
end
// Fetch next word for line
else
begin
line_word <= line_word + 1'b1;
state <= STATE_WRITE;
if (line_word == ({CACHE_LINE_WORDS_IDX_MAX{1'b1}}-1))
mem_burst_o <= 1'b0;
end
end
end
//-----------------------------------------
// READ_SINGLE - Single access to memory
//-----------------------------------------
STATE_READ_SINGLE:
begin
// Data ready from memory?
if (mem_ack_i && mem_rd_o == 1'b0)
begin
data_o <= mem_data_i;
done_o <= 1'b1;
state <= STATE_IDLE;
end
end
//-----------------------------------------
// WRITE_SINGLE - Single access to memory
//-----------------------------------------
STATE_WRITE_SINGLE:
begin
if (mem_ack_i && mem_wr_o == 4'b0)
begin
done_o <= 1'b1;
state <= STATE_IDLE;
end
end
default:
;
endcase
end
end
 
endmodule
/rtl/cpu/altor32_exec.v
0,0 → 1,1377
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//`define CONF_CORE_DEBUG
//`define CONF_CORE_DEBUG_BUBBLE
//`define CONF_CORE_TRACE
//`define CONF_CORE_FAULT_ON_OPCODE0
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Instruction Execute
//-----------------------------------------------------------------
module altor32_exec
(
// General
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
// Maskable interrupt
input intr_i /*verilator public*/,
 
// Unmaskable interrupt
input nmi_i /*verilator public*/,
 
// Fault
output reg fault_o /*verilator public*/,
 
// Breakpoint / Trap
output reg break_o /*verilator public*/,
 
// Cache control
output reg icache_flush_o /*verilator public*/,
output reg dcache_flush_o /*verilator public*/,
// Branch
output branch_o /*verilator public*/,
output [31:0] branch_pc_o /*verilator public*/,
output stall_o /*verilator public*/,
 
// Opcode & arguments
input [31:0] opcode_i /*verilator public*/,
input [31:0] opcode_pc_i /*verilator public*/,
input opcode_valid_i /*verilator public*/,
 
// Reg A
input [4:0] reg_ra_i /*verilator public*/,
input [31:0] reg_ra_value_i /*verilator public*/,
 
// Reg B
input [4:0] reg_rb_i /*verilator public*/,
input [31:0] reg_rb_value_i /*verilator public*/,
 
// Reg D
input [4:0] reg_rd_i /*verilator public*/,
 
// Output
output [31:0] opcode_o /*verilator public*/,
output [4:0] reg_rd_o /*verilator public*/,
output [31:0] reg_rd_value_o /*verilator public*/,
output mult_o /*verilator public*/,
output [31:0] mult_res_o /*verilator public*/,
 
// Register write back bypass
input [4:0] wb_rd_i /*verilator public*/,
input [31:0] wb_rd_value_i /*verilator public*/,
 
// Memory Interface
output reg [31:0] dmem_addr_o /*verilator public*/,
output reg [31:0] dmem_data_out_o /*verilator public*/,
input [31:0] dmem_data_in_i /*verilator public*/,
output reg [3:0] dmem_wr_o /*verilator public*/,
output reg dmem_rd_o /*verilator public*/,
input dmem_accept_i /*verilator public*/,
input dmem_ack_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
parameter ISR_VECTOR = 32'h00000000;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
 
// Branch PC
reg [31:0] r_pc_branch;
reg r_pc_fetch;
reg r_stall;
 
// Exception saved program counter
reg [31:0] r_epc;
 
// Supervisor register
reg [31:0] r_sr;
 
// Exception saved supervisor register
reg [31:0] r_esr;
 
// Destination register number (post execute stage)
reg [4:0] r_e_rd;
 
// Current opcode (PC for debug)
reg [31:0] r_e_opcode;
reg [31:0] r_e_opcode_pc;
 
// ALU input A
reg [31:0] r_e_alu_a;
 
// ALU input B
reg [31:0] r_e_alu_b;
 
// ALU output
wire [31:0] r_e_result;
 
// Resolved RA/RB register contents
wire [31:0] ra_value_resolved;
wire [31:0] rb_value_resolved;
wire resolve_failed;
 
// ALU Carry
wire alu_carry_out;
wire alu_carry_update;
 
// ALU operation selection
reg [3:0] r_e_alu_func;
 
// Load instruction details
reg [4:0] r_load_rd;
reg [7:0] r_load_inst;
reg [1:0] r_load_offset;
 
// Load forwarding
wire load_insn;
wire [31:0] load_result;
 
// Memory access?
reg r_mem_load;
reg r_mem_store;
reg r_mem_access;
 
wire load_pending;
wire store_pending;
wire load_insert;
wire load_stall;
 
reg d_mem_load;
 
// Delayed NMI
reg r_nmi;
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
 
// ALU
altor32_alu alu
(
// ALU operation select
.op_i(r_e_alu_func),
 
// Operands
.a_i(r_e_alu_a),
.b_i(r_e_alu_b),
.c_i(r_sr[`OR32_SR_CY]),
 
// Result
.p_o(r_e_result),
 
// Carry
.c_o(alu_carry_out),
.c_update_o(alu_carry_update)
);
 
// Load result forwarding
altor32_lfu
u_lfu
(
// Opcode
.opcode_i(r_load_inst),
 
// Memory load result
.mem_result_i(dmem_data_in_i),
.mem_offset_i(r_load_offset),
 
// Result
.load_result_o(load_result),
.load_insn_o(load_insn)
);
 
// Load / store pending logic
altor32_lsu
u_lsu
(
// Current instruction
.opcode_valid_i(opcode_valid_i & ~r_pc_fetch),
.opcode_i({2'b00,opcode_i[31:26]}),
 
// Load / Store pending
.load_pending_i(r_mem_load),
.store_pending_i(r_mem_store),
 
// Load dest register
.rd_load_i(r_load_rd),
 
// Load insn in WB stage
.load_wb_i(d_mem_load),
 
// Memory status
.mem_access_i(r_mem_access),
.mem_ack_i(dmem_ack_i),
 
// Load / store still pending
.load_pending_o(load_pending),
.store_pending_o(store_pending),
 
// Insert load result into pipeline
.write_result_o(load_insert),
 
// Stall pipeline due
.stall_o(load_stall)
);
 
// Operand forwarding
altor32_dfu
u_dfu
(
// Input registers
.ra_i(reg_ra_i),
.rb_i(reg_rb_i),
 
// Input register contents
.ra_regval_i(reg_ra_value_i),
.rb_regval_i(reg_rb_value_i),
 
// Dest register (EXEC stage)
.rd_ex_i(r_e_rd),
 
// Dest register (WB stage)
.rd_wb_i(wb_rd_i),
 
// Load pending / target
.load_pending_i(load_pending),
.rd_load_i(r_load_rd),
 
// Multiplier status
.mult_lo_ex_i(1'b0),
.mult_hi_ex_i(1'b0),
.mult_lo_wb_i(1'b0),
.mult_hi_wb_i(1'b0),
 
// Multiplier result
.result_mult_i(64'b0),
 
// Result (EXEC)
.result_ex_i(r_e_result),
 
// Result (WB)
.result_wb_i(wb_rd_value_i),
 
// Resolved register values
.result_ra_o(ra_value_resolved),
.result_rb_o(rb_value_resolved),
 
// Stall due to failed resolve
.stall_o(resolve_failed)
);
 
//-------------------------------------------------------------------
// Execute: Execute opcode
//-------------------------------------------------------------------
 
// Execute stage blocking assignment vars
reg [7:0] v_inst;
reg [4:0] v_rd;
reg [7:0] v_alu_op;
reg [1:0] v_shift_op;
reg [15:0] v_sfxx_op;
reg [15:0] v_imm;
reg [31:0] v_imm_uint32;
reg [31:0] v_imm_int32;
reg [31:0] v_store_imm;
reg [15:0] v_mxspr_imm;
reg [31:0] v_target;
reg [31:0] v_reg_ra;
reg [31:0] v_reg_rb;
reg [31:0] v_pc;
reg [31:0] v_offset;
reg [31:0] v_shift_val;
reg [31:0] v_shift_imm;
reg [31:0] v_vector;
reg [31:0] v_sr;
reg [31:0] v_mem_addr;
reg [31:0] v_mem_data_in;
reg v_exception;
reg v_branch;
reg v_jmp;
reg v_write_rd;
reg v_store_pending;
reg v_load_pending;
reg v_inst_load;
reg v_inst_store;
reg v_stall;
reg v_no_intr;
reg v_opcode_valid;
reg v_check_load_rd;
 
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
r_pc_branch <= 32'h00000000;
r_pc_fetch <= 1'b0;
r_stall <= 1'b0;
 
// Status registers
r_epc <= 32'h00000000;
r_sr <= 32'h00000000;
r_esr <= 32'h00000000;
r_e_rd <= 5'b00000;
 
// Default to no ALU operation
r_e_alu_func <= `ALU_NONE;
r_e_alu_a <= 32'h00000000;
r_e_alu_b <= 32'h00000000;
r_e_opcode <= 32'h00000000;
r_e_opcode_pc <= 32'h00000000;
 
// Data memory
dmem_addr_o <= 32'h00000000;
dmem_data_out_o <= 32'h00000000;
dmem_rd_o <= 1'b0;
dmem_wr_o <= 4'b0000;
 
fault_o <= 1'b0;
break_o <= 1'b0;
 
r_nmi <= 1'b0;
icache_flush_o <= 1'b0;
dcache_flush_o <= 1'b0;
r_mem_load <= 1'b0;
r_mem_store <= 1'b0;
r_mem_access <= 1'b0;
r_load_rd <= 5'b00000;
r_load_inst <= 8'h00;
r_load_offset <= 2'b00;
 
d_mem_load <= 1'b0;
end
else
begin
 
// If memory access accepted by slave
if (dmem_accept_i)
begin
dmem_rd_o <= 1'b0;
dmem_wr_o <= 4'b0000;
end
r_mem_access <= 1'b0;
break_o <= 1'b0;
icache_flush_o <= 1'b0;
dcache_flush_o <= 1'b0;
 
// Record NMI in-case it can't be processed this cycle
if (nmi_i)
r_nmi <= 1'b1;
// Reset branch request
r_pc_fetch <= 1'b0;
 
v_exception = 1'b0;
v_vector = 32'h00000000;
v_branch = 1'b0;
v_jmp = 1'b0;
v_write_rd = 1'b0;
v_sr = r_sr;
v_stall = 1'b0;
v_no_intr = 1'b0;
 
d_mem_load <= r_mem_access & r_mem_load;
 
//---------------------------------------------------------------
// Opcode
//---------------------------------------------------------------
 
// Instruction not ready
if (!opcode_valid_i)
begin
v_opcode_valid = 1'b0;
`ifdef CONF_CORE_DEBUG_BUBBLE
$display("%08x: Execute - Instruction not ready", opcode_pc_i);
`endif
end
// Branch request, always drop the next instruction
else if (r_pc_fetch)
begin
v_opcode_valid = 1'b0;
`ifdef CONF_CORE_DEBUG
$display("%08x: Exec - Branch pending, skip instruction (%x)", opcode_pc_i, opcode_i);
`endif
end
// Valid instruction ready
else
begin
v_mem_data_in = opcode_i;
v_opcode_valid = 1'b1;
 
`ifdef CONF_CORE_FAULT_ON_OPCODE0
// This is a valid opcode (branch to same instruction),
// but rare and useful for catching pipeline errors
if (v_mem_data_in == 32'h00000000)
fault_o <= 1'b1;
`endif
end
 
//---------------------------------------------------------------
// Decode opcode
//---------------------------------------------------------------
v_alu_op = {v_mem_data_in[9:6],v_mem_data_in[3:0]};
v_sfxx_op = {5'b00,v_mem_data_in[31:21]};
v_shift_op = v_mem_data_in[7:6];
v_target = sign_extend_imm26(v_mem_data_in[25:0]);
v_store_imm = sign_extend_imm16({v_mem_data_in[25:21],v_mem_data_in[10:0]});
 
// Signed & unsigned imm -> 32-bits
v_imm = v_mem_data_in[15:0];
v_imm_int32 = sign_extend_imm16(v_imm);
v_imm_uint32 = extend_imm16(v_imm);
 
// Load register[ra]
v_reg_ra = ra_value_resolved;
 
// Load register[rb]
v_reg_rb = rb_value_resolved;
// Default to no ALU operation (output == input_a)
r_e_alu_func <= `ALU_NONE;
r_e_alu_a <= 32'h00000000;
// Default target is R[d]
v_rd = reg_rd_i;
//---------------------------------------------------------------
// Outstanding memory access
//---------------------------------------------------------------
 
// Pending accesses
v_load_pending = load_pending;
v_store_pending = store_pending;
v_check_load_rd = 1'b1;
// Stall pipeline due to load / store
if (v_opcode_valid & load_stall)
begin
v_stall = 1'b1;
v_opcode_valid = 1'b0;
end
 
// Insert load result into pipeline?
if (load_insert)
begin
// Feed load result into pipeline
r_e_alu_func <= `ALU_NONE;
r_e_alu_a <= load_result;
v_rd = r_load_rd;
v_write_rd = 1'b1;
end
 
//---------------------------------------------------------------
// Invalid PC detection
//---------------------------------------------------------------
// Detect incorrect program counter and cause FAULT
if (opcode_valid_i && (opcode_pc_i[1:0] != 2'b00))
begin
fault_o <= 1'b1;
v_opcode_valid = 1'b0;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_BUS_ERROR;
end
//---------------------------------------------------------------
// Failed operand resolve?
//---------------------------------------------------------------
if (opcode_valid_i & resolve_failed)
begin
`ifdef CONF_CORE_DEBUG
$display("%08x: Operand resolve failed RA=%d, RB=%d", opcode_pc_i, reg_ra_i, reg_rb_i);
`endif
// Stall!
v_opcode_valid = 1'b0;
v_stall = 1'b1;
end
//---------------------------------------------------------------
// Final instruction decoding
//---------------------------------------------------------------
// Insert bubble into the pipeline?
if (!v_opcode_valid)
begin
v_mem_data_in = `OPCODE_INST_BUBBLE;
v_check_load_rd = 1'b0;
end
 
// Store opcode (after possible bubble generation)
r_e_opcode <= v_mem_data_in;
r_e_opcode_pc <= opcode_pc_i;
 
// Decode instruction
v_inst = {2'b00,v_mem_data_in[31:26]};
 
// Shift ammount (from register[rb])
v_shift_val = {26'b00,v_reg_rb[5:0]};
 
// Shift ammount (from immediate)
v_shift_imm = {26'b00,v_imm[5:0]};
 
// MTSPR/MFSPR operand
v_mxspr_imm = (v_reg_ra[15:0] | {5'b00000,v_mem_data_in[10:0]});
 
// Next expected PC (current PC + 4)
v_pc = (opcode_pc_i + 4);
// Latch carry if updated
if (alu_carry_update)
v_sr[`OR32_SR_CY] = alu_carry_out;
 
`ifdef CONF_CORE_TRACE
if (v_opcode_valid)
begin
$display("%08x: Execute 0x%08x", opcode_pc_i, v_mem_data_in);
$display(" rA[%d] = 0x%08x", reg_ra_i, v_reg_ra);
$display(" rB[%d] = 0x%08x", reg_rb_i, v_reg_rb);
end
`endif
 
//---------------------------------------------------------------
// Execute instruction
//---------------------------------------------------------------
case (v_inst)
`INST_OR32_BUBBLE :
begin
// Do not allow external interrupts whilst executing a bubble
// as this will result in pipeline issues.
v_no_intr = 1'b1;
end
`INST_OR32_ALU :
begin
case (v_alu_op)
`INST_OR32_ADD: // l.add
begin
r_e_alu_func <= `ALU_ADD;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_reg_rb;
v_write_rd = 1'b1;
end
`INST_OR32_ADDC: // l.addc
begin
r_e_alu_func <= `ALU_ADDC;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_reg_rb;
v_write_rd = 1'b1;
end
 
`INST_OR32_AND: // l.and
begin
r_e_alu_func <= `ALU_AND;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_reg_rb;
v_write_rd = 1'b1;
end
 
`INST_OR32_OR: // l.or
begin
r_e_alu_func <= `ALU_OR;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_reg_rb;
v_write_rd = 1'b1;
end
 
`INST_OR32_SLL: // l.sll
begin
r_e_alu_func <= `ALU_SHIFTL;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_shift_val;
v_write_rd = 1'b1;
end
 
`INST_OR32_SRA: // l.sra
begin
r_e_alu_func <= `ALU_SHIRTR_ARITH;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_shift_val;
v_write_rd = 1'b1;
end
 
`INST_OR32_SRL: // l.srl
begin
r_e_alu_func <= `ALU_SHIFTR;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_shift_val;
v_write_rd = 1'b1;
end
 
`INST_OR32_SUB: // l.sub
begin
r_e_alu_func <= `ALU_SUB;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_reg_rb;
v_write_rd = 1'b1;
end
 
`INST_OR32_XOR: // l.xor
begin
r_e_alu_func <= `ALU_XOR;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_reg_rb;
v_write_rd = 1'b1;
end
 
default:
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
end
 
`INST_OR32_ADDI: // l.addi
begin
r_e_alu_func <= `ALU_ADD;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_imm_int32;
v_write_rd = 1'b1;
end
 
`INST_OR32_ANDI: // l.andi
begin
r_e_alu_func <= `ALU_AND;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_imm_uint32;
v_write_rd = 1'b1;
end
 
`INST_OR32_BF: // l.bf
begin
if (v_sr[`OR32_SR_F] == 1'b1)
v_branch = 1'b1;
end
 
`INST_OR32_BNF: // l.bnf
begin
if (v_sr[`OR32_SR_F] == 1'b0)
v_branch = 1'b1;
end
 
`INST_OR32_J: // l.j
begin
v_branch = 1'b1;
end
 
`INST_OR32_JAL: // l.jal
begin
r_e_alu_a <= v_pc;
v_write_rd = 1'b1;
v_rd = 5'b01001; // Write to REG_9_LR
`ifdef CONF_CORE_DEBUG
$display(" Save 0x%x to LR", v_pc);
`endif
v_branch = 1'b1;
end
 
`INST_OR32_JALR: // l.jalr
begin
r_e_alu_a <= v_pc;
v_write_rd = 1'b1;
v_rd = 5'b01001; // Write to REG_9_LR
`ifdef CONF_CORE_DEBUG
$display(" Save 0x%x to LR", v_pc);
`endif
v_pc = v_reg_rb;
v_jmp = 1;
end
 
`INST_OR32_JR: // l.jr
begin
v_pc = v_reg_rb;
v_jmp = 1;
end
 
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
`INST_OR32_LBS, `INST_OR32_LHS, `INST_OR32_LWS, `INST_OR32_LBZ, `INST_OR32_LHZ, `INST_OR32_LWZ :
begin
v_mem_addr = (v_reg_ra + v_imm_int32);
dmem_addr_o <= v_mem_addr;
dmem_data_out_o <= 32'h00000000;
dmem_rd_o <= 1'b1;
// Writeback if load result ready
v_write_rd = 1'b1;
v_check_load_rd = 1'b0;
// Mark load as pending
v_load_pending = 1'b1;
r_mem_access <= 1'b1;
// Record target register
r_load_rd <= reg_rd_i;
r_load_inst <= v_inst;
r_load_offset<= v_mem_addr[1:0];
`ifdef CONF_CORE_DEBUG
$display(" Load from 0x%08x to R%d", v_mem_addr, reg_rd_i);
`endif
// Detect bad load address & fault (ignore bit 31)
if (v_mem_addr[30:28] != 3'h1)
begin
v_load_pending = 1'b0;
dmem_rd_o <= 1'b0;
r_mem_access <= 1'b0;
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_BUS_ERROR;
end
end
 
`INST_OR32_MFSPR: // l.mfspr
begin
case (v_mxspr_imm)
// SR - Supervision register
`SPR_REG_SR:
begin
r_e_alu_a <= v_sr;
v_write_rd = 1'b1;
end
 
// EPCR - EPC Exception saved PC
`SPR_REG_EPCR:
begin
r_e_alu_a <= r_epc;
v_write_rd = 1'b1;
end
 
// ESR - Exception saved SR
`SPR_REG_ESR:
begin
r_e_alu_a <= r_esr;
v_write_rd = 1'b1;
end
 
default:
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
end
 
`INST_OR32_MTSPR: // l.mtspr
begin
case (v_mxspr_imm)
// SR - Supervision register
`SPR_REG_SR:
begin
v_sr = v_reg_rb;
// Cache flush request?
icache_flush_o <= v_reg_rb[`OR32_SR_ICACHE_FLUSH];
dcache_flush_o <= v_reg_rb[`OR32_SR_DCACHE_FLUSH];
// Don't store cache flush requests
v_sr[`OR32_SR_ICACHE_FLUSH] = 1'b0;
v_sr[`OR32_SR_DCACHE_FLUSH] = 1'b0;
end
 
// EPCR - EPC Exception saved PC
`SPR_REG_EPCR:
begin
r_epc <= v_reg_rb;
end
 
// ESR - Exception saved SR
`SPR_REG_ESR:
begin
r_esr <= v_reg_rb;
end
default:
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
end
 
`INST_OR32_MOVHI: // l.movhi
begin
r_e_alu_a <= {v_imm,16'h0000};
v_write_rd = 1'b1;
end
 
`INST_OR32_NOP: // l.nop
begin
`ifdef SIMULATION
case (v_imm)
// NOP_PUTC
16'h0004: $write("%c", v_reg_ra[7:0]);
// NOP
16'h0000: ;
endcase
`endif
end
 
`INST_OR32_ORI: // l.ori
begin
r_e_alu_func <= `ALU_OR;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_imm_uint32;
v_write_rd = 1'b1;
end
 
`INST_OR32_RFE: // l.rfe
begin
v_pc = r_epc;
v_sr = r_esr;
v_jmp = 1;
end
 
`INST_OR32_SHIFTI :
begin
case (v_shift_op)
`INST_OR32_SLLI: // l.slli
begin
r_e_alu_func <= `ALU_SHIFTL;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_shift_imm;
v_write_rd = 1'b1;
end
 
`INST_OR32_SRAI: // l.srai
begin
r_e_alu_func <= `ALU_SHIRTR_ARITH;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_shift_imm;
v_write_rd = 1'b1;
end
 
`INST_OR32_SRLI: // l.srli
begin
r_e_alu_func <= `ALU_SHIFTR;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_shift_imm;
v_write_rd = 1'b1;
end
 
default:
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
end
 
`INST_OR32_SB:
begin
v_mem_addr = (v_reg_ra + v_store_imm);
dmem_addr_o <= v_mem_addr;
r_mem_access <= 1'b1;
case (v_mem_addr[1:0])
2'b00 :
begin
dmem_data_out_o <= {v_reg_rb[7:0],24'h000000};
dmem_wr_o <= 4'b1000;
v_store_pending = 1'b1;
end
2'b01 :
begin
dmem_data_out_o <= {{8'h00,v_reg_rb[7:0]},16'h0000};
dmem_wr_o <= 4'b0100;
v_store_pending = 1'b1;
end
2'b10 :
begin
dmem_data_out_o <= {{16'h0000,v_reg_rb[7:0]},8'h00};
dmem_wr_o <= 4'b0010;
v_store_pending = 1'b1;
end
2'b11 :
begin
dmem_data_out_o <= {24'h000000,v_reg_rb[7:0]};
dmem_wr_o <= 4'b0001;
v_store_pending = 1'b1;
end
default :
begin
dmem_data_out_o <= 32'h00000000;
dmem_wr_o <= 4'b0000;
end
endcase
end
 
`INST_OR32_SFXX, `INST_OR32_SFXXI:
begin
case (v_sfxx_op)
`INST_OR32_SFEQ: // l.sfeq
begin
if (v_reg_ra == v_reg_rb)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFEQI: // l.sfeqi
begin
if (v_reg_ra == v_imm_int32)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGES: // l.sfges
begin
if (greater_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGESI: // l.sfgesi
begin
if (greater_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGEU: // l.sfgeu
begin
if (v_reg_ra >= v_reg_rb)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGEUI: // l.sfgeui
begin
if (v_reg_ra >= v_imm_int32)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGTS: // l.sfgts
begin
if (greater_than_signed(v_reg_ra, v_reg_rb) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGTSI: // l.sfgtsi
begin
if (greater_than_signed(v_reg_ra, v_imm_int32) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGTU: // l.sfgtu
begin
if (v_reg_ra > v_reg_rb)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFGTUI: // l.sfgtui
begin
if (v_reg_ra > v_imm_int32)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLES: // l.sfles
begin
if (less_than_equal_signed(v_reg_ra, v_reg_rb) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLESI: // l.sflesi
begin
if (less_than_equal_signed(v_reg_ra, v_imm_int32) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLEU: // l.sfleu
begin
if (v_reg_ra <= v_reg_rb)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLEUI: // l.sfleui
begin
if (v_reg_ra <= v_imm_int32)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLTS: // l.sflts
begin
if (less_than_signed(v_reg_ra, v_reg_rb) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLTSI: // l.sfltsi
begin
if (less_than_signed(v_reg_ra, v_imm_int32) == 1'b1)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLTU: // l.sfltu
begin
if (v_reg_ra < v_reg_rb)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFLTUI: // l.sfltui
begin
if (v_reg_ra < v_imm_int32)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFNE: // l.sfne
begin
if (v_reg_ra != v_reg_rb)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
`INST_OR32_SFNEI: // l.sfnei
begin
if (v_reg_ra != v_imm_int32)
v_sr[`OR32_SR_F] = 1'b1;
else
v_sr[`OR32_SR_F] = 1'b0;
end
 
default:
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
end
 
`INST_OR32_SH: // l.sh
begin
v_mem_addr = (v_reg_ra + v_store_imm);
dmem_addr_o <= v_mem_addr;
r_mem_access <= 1'b1;
case (v_mem_addr[1:0])
2'b00 :
begin
dmem_data_out_o <= {v_reg_rb[15:0],16'h0000};
dmem_wr_o <= 4'b1100;
v_store_pending = 1'b1;
end
2'b10 :
begin
dmem_data_out_o <= {16'h0000,v_reg_rb[15:0]};
dmem_wr_o <= 4'b0011;
v_store_pending = 1'b1;
end
default :
begin
dmem_data_out_o <= 32'h00000000;
dmem_wr_o <= 4'b0000;
end
endcase
end
 
`INST_OR32_SW: // l.sw
begin
v_mem_addr = (v_reg_ra + v_store_imm);
dmem_addr_o <= v_mem_addr;
dmem_data_out_o <= v_reg_rb;
dmem_wr_o <= 4'b1111;
r_mem_access <= 1'b1;
v_store_pending = 1'b1;
 
`ifdef CONF_CORE_DEBUG
$display(" Store R%d to 0x%08x = 0x%08x", reg_rb_i, {v_mem_addr[31:2],2'b00}, v_reg_rb);
`endif
end
 
`INST_OR32_MISC:
begin
case (v_mem_data_in[31:24])
`INST_OR32_SYS: // l.sys
begin
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_SYSCALL;
end
 
`INST_OR32_TRAP: // l.trap
begin
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_TRAP;
break_o <= 1'b1;
end
 
default :
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
end
 
`INST_OR32_XORI: // l.xori
begin
r_e_alu_func <= `ALU_XOR;
r_e_alu_a <= v_reg_ra;
r_e_alu_b <= v_imm_int32;
v_write_rd = 1'b1;
end
 
default :
begin
fault_o <= 1'b1;
v_exception = 1'b1;
v_vector = ISR_VECTOR + `VECTOR_ILLEGAL_INST;
end
endcase
 
//---------------------------------------------------------------
// Branch logic
//---------------------------------------------------------------
 
// If relative branch, calculate target before possible interrupt/exception
if (v_branch == 1'b1)
begin
v_offset = {v_target[29:0],2'b00};
v_pc = (opcode_pc_i + v_offset);
end
// Pipeline stall due to load result not ready
if (v_stall == 1'b1)
begin
// No exceptions whilst stalled
end
// Exception (Fault/Syscall/Break)
else if (v_exception == 1'b1)
begin
// Save PC of next instruction
r_epc <= v_pc;
 
// Disable further interrupts
r_esr <= v_sr;
v_sr = 0;
 
// Set PC to exception vector
v_pc = v_vector;
r_pc_branch <= v_pc;
r_pc_fetch <= 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" Exception 0x%08x", v_vector);
`endif
end
// Non-maskable interrupt
else if (nmi_i | r_nmi)
begin
r_nmi <= 1'b0;
 
// Save PC of next instruction
r_epc <= v_pc;
 
// Disable further interrupts
r_esr <= v_sr;
v_sr = 0;
 
// Set PC to exception vector
v_pc = ISR_VECTOR + `VECTOR_NMI;
r_pc_branch <= v_pc;
r_pc_fetch <= 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" NMI 0x%08x", v_pc);
`endif
end
// External interrupt
else if (v_no_intr == 1'b0 &&
((intr_i && v_sr[`OR32_SR_IEE])))
begin
// Save PC of next instruction & SR
r_epc <= v_pc;
 
// Disable further interrupts
r_esr <= v_sr;
v_sr = 0;
 
// Set PC to external interrupt vector
v_pc = ISR_VECTOR + `VECTOR_EXTINT;
 
r_pc_branch <= v_pc;
r_pc_fetch <= 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" External Interrupt 0x%08x", v_pc);
`endif
end
// Handle relative branches (l.bf, l.bnf, l.j, l.jal)
else if (v_branch == 1'b1)
begin
// Perform branch (already in v_pc)
r_pc_branch <= v_pc;
r_pc_fetch <= 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" Branch to 0x%08x", v_pc);
`endif
end
// Handle absolute jumps (l.jr, l.jalr, l.rfe)
else if (v_jmp == 1'b1)
begin
// Perform branch
r_pc_branch <= v_pc;
r_pc_fetch <= 1'b1;
`ifdef CONF_CORE_DEBUG
$display(" Jump to 0x%08x", v_pc);
`endif
end
 
 
// Update other registers with variable values
r_stall <= v_stall;
r_sr <= v_sr;
 
// Memory access?
r_mem_load <= v_load_pending;
r_mem_store<= v_store_pending;
// No writeback required?
if (v_write_rd == 1'b0)
begin
// Target register is R0 which is read-only
r_e_rd <= 5'b00000;
end
// Writeback required
else
begin
// Load outstanding, check if result target is being
// overwritten (to avoid WAR hazard)
if (v_check_load_rd && v_rd == r_load_rd)
begin
`ifdef CONF_CORE_DEBUG
if (v_rd != 5'b0)
$display("%08x: Load target overwrite, clear target (R%d)", opcode_pc_i, r_load_rd);
`endif
 
// Ditch load result when it arrives
r_load_rd <= 5'b00000;
end
 
// Target Rd
r_e_rd <= v_rd;
end
end
end
 
//-------------------------------------------------------------------
// Assignments
//-------------------------------------------------------------------
 
assign branch_pc_o = r_pc_branch;
assign branch_o = r_pc_fetch;
assign stall_o = r_stall;
 
assign opcode_o = r_e_opcode;
 
assign reg_rd_o = r_e_rd;
assign reg_rd_value_o = r_e_result;
 
assign mult_o = 1'b0;
assign mult_res_o = 32'b0;
 
`include "altor32_funcs.v"
 
//-------------------------------------------------------------------
// Hooks for debug
//-------------------------------------------------------------------
`ifdef verilator
function [31:0] get_opcode_ex;
// verilator public
get_opcode_ex = r_e_opcode;
endfunction
function [31:0] get_pc_ex;
// verilator public
get_pc_ex = r_e_opcode_pc;
endfunction
`endif
 
endmodule
/rtl/cpu/altor32_regfile_sim.v
0,0 → 1,444
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Simulation register file
//-----------------------------------------------------------------
module altor32_regfile_sim
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output [31:0] reg_rs_o /*verilator public*/,
output [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter SUPPORT_32REGS = "ENABLED";
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
 
// Register file
reg [31:0] reg_r1_sp;
reg [31:0] reg_r2_fp;
reg [31:0] reg_r3;
reg [31:0] reg_r4;
reg [31:0] reg_r5;
reg [31:0] reg_r6;
reg [31:0] reg_r7;
reg [31:0] reg_r8;
reg [31:0] reg_r9_lr;
reg [31:0] reg_r10;
reg [31:0] reg_r11;
reg [31:0] reg_r12;
reg [31:0] reg_r13;
reg [31:0] reg_r14;
reg [31:0] reg_r15;
reg [31:0] reg_r16;
reg [31:0] reg_r17;
reg [31:0] reg_r18;
reg [31:0] reg_r19;
reg [31:0] reg_r20;
reg [31:0] reg_r21;
reg [31:0] reg_r22;
reg [31:0] reg_r23;
reg [31:0] reg_r24;
reg [31:0] reg_r25;
reg [31:0] reg_r26;
reg [31:0] reg_r27;
reg [31:0] reg_r28;
reg [31:0] reg_r29;
reg [31:0] reg_r30;
reg [31:0] reg_r31;
 
reg [31:0] reg_rs_o;
reg [31:0] reg_rt_o;
 
//-----------------------------------------------------------------
// Register File (for simulation)
//-----------------------------------------------------------------
 
// Synchronous register write back
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i)
begin
reg_r1_sp <= 32'h00000000;
reg_r2_fp <= 32'h00000000;
reg_r3 <= 32'h00000000;
reg_r4 <= 32'h00000000;
reg_r5 <= 32'h00000000;
reg_r6 <= 32'h00000000;
reg_r7 <= 32'h00000000;
reg_r8 <= 32'h00000000;
reg_r9_lr <= 32'h00000000;
reg_r10 <= 32'h00000000;
reg_r11 <= 32'h00000000;
reg_r12 <= 32'h00000000;
reg_r13 <= 32'h00000000;
reg_r14 <= 32'h00000000;
reg_r15 <= 32'h00000000;
reg_r16 <= 32'h00000000;
reg_r17 <= 32'h00000000;
reg_r18 <= 32'h00000000;
reg_r19 <= 32'h00000000;
reg_r20 <= 32'h00000000;
reg_r21 <= 32'h00000000;
reg_r22 <= 32'h00000000;
reg_r23 <= 32'h00000000;
reg_r24 <= 32'h00000000;
reg_r25 <= 32'h00000000;
reg_r26 <= 32'h00000000;
reg_r27 <= 32'h00000000;
reg_r28 <= 32'h00000000;
reg_r29 <= 32'h00000000;
reg_r30 <= 32'h00000000;
reg_r31 <= 32'h00000000;
end
else
begin
if (wr_i == 1'b1)
case (rd_i[4:0])
5'b00001 :
reg_r1_sp <= reg_rd_i;
5'b00010 :
reg_r2_fp <= reg_rd_i;
5'b00011 :
reg_r3 <= reg_rd_i;
5'b00100 :
reg_r4 <= reg_rd_i;
5'b00101 :
reg_r5 <= reg_rd_i;
5'b00110 :
reg_r6 <= reg_rd_i;
5'b00111 :
reg_r7 <= reg_rd_i;
5'b01000 :
reg_r8 <= reg_rd_i;
5'b01001 :
reg_r9_lr <= reg_rd_i;
5'b01010 :
reg_r10 <= reg_rd_i;
5'b01011 :
reg_r11 <= reg_rd_i;
5'b01100 :
reg_r12 <= reg_rd_i;
5'b01101 :
reg_r13 <= reg_rd_i;
5'b01110 :
reg_r14 <= reg_rd_i;
5'b01111 :
reg_r15 <= reg_rd_i;
5'b10000 :
reg_r16 <= reg_rd_i;
5'b10001 :
reg_r17 <= reg_rd_i;
5'b10010 :
reg_r18 <= reg_rd_i;
5'b10011 :
reg_r19 <= reg_rd_i;
5'b10100 :
reg_r20 <= reg_rd_i;
5'b10101 :
reg_r21 <= reg_rd_i;
5'b10110 :
reg_r22 <= reg_rd_i;
5'b10111 :
reg_r23 <= reg_rd_i;
5'b11000 :
reg_r24 <= reg_rd_i;
5'b11001 :
reg_r25 <= reg_rd_i;
5'b11010 :
reg_r26 <= reg_rd_i;
5'b11011 :
reg_r27 <= reg_rd_i;
5'b11100 :
reg_r28 <= reg_rd_i;
5'b11101 :
reg_r29 <= reg_rd_i;
5'b11110 :
reg_r30 <= reg_rd_i;
5'b11111 :
reg_r31 <= reg_rd_i;
default :
;
endcase
end
end
 
generate
if (SUPPORT_32REGS == "ENABLED")
begin
// Asynchronous Register read (Rs & Rd)
always @ *
begin
case (rs_i)
5'b00000 :
reg_rs_o = 32'h00000000;
5'b00001 :
reg_rs_o = reg_r1_sp;
5'b00010 :
reg_rs_o = reg_r2_fp;
5'b00011 :
reg_rs_o = reg_r3;
5'b00100 :
reg_rs_o = reg_r4;
5'b00101 :
reg_rs_o = reg_r5;
5'b00110 :
reg_rs_o = reg_r6;
5'b00111 :
reg_rs_o = reg_r7;
5'b01000 :
reg_rs_o = reg_r8;
5'b01001 :
reg_rs_o = reg_r9_lr;
5'b01010 :
reg_rs_o = reg_r10;
5'b01011 :
reg_rs_o = reg_r11;
5'b01100 :
reg_rs_o = reg_r12;
5'b01101 :
reg_rs_o = reg_r13;
5'b01110 :
reg_rs_o = reg_r14;
5'b01111 :
reg_rs_o = reg_r15;
5'b10000 :
reg_rs_o = reg_r16;
5'b10001 :
reg_rs_o = reg_r17;
5'b10010 :
reg_rs_o = reg_r18;
5'b10011 :
reg_rs_o = reg_r19;
5'b10100 :
reg_rs_o = reg_r20;
5'b10101 :
reg_rs_o = reg_r21;
5'b10110 :
reg_rs_o = reg_r22;
5'b10111 :
reg_rs_o = reg_r23;
5'b11000 :
reg_rs_o = reg_r24;
5'b11001 :
reg_rs_o = reg_r25;
5'b11010 :
reg_rs_o = reg_r26;
5'b11011 :
reg_rs_o = reg_r27;
5'b11100 :
reg_rs_o = reg_r28;
5'b11101 :
reg_rs_o = reg_r29;
5'b11110 :
reg_rs_o = reg_r30;
5'b11111 :
reg_rs_o = reg_r31;
default :
reg_rs_o = 32'h00000000;
endcase
 
case (rt_i)
5'b00000 :
reg_rt_o = 32'h00000000;
5'b00001 :
reg_rt_o = reg_r1_sp;
5'b00010 :
reg_rt_o = reg_r2_fp;
5'b00011 :
reg_rt_o = reg_r3;
5'b00100 :
reg_rt_o = reg_r4;
5'b00101 :
reg_rt_o = reg_r5;
5'b00110 :
reg_rt_o = reg_r6;
5'b00111 :
reg_rt_o = reg_r7;
5'b01000 :
reg_rt_o = reg_r8;
5'b01001 :
reg_rt_o = reg_r9_lr;
5'b01010 :
reg_rt_o = reg_r10;
5'b01011 :
reg_rt_o = reg_r11;
5'b01100 :
reg_rt_o = reg_r12;
5'b01101 :
reg_rt_o = reg_r13;
5'b01110 :
reg_rt_o = reg_r14;
5'b01111 :
reg_rt_o = reg_r15;
5'b10000 :
reg_rt_o = reg_r16;
5'b10001 :
reg_rt_o = reg_r17;
5'b10010 :
reg_rt_o = reg_r18;
5'b10011 :
reg_rt_o = reg_r19;
5'b10100 :
reg_rt_o = reg_r20;
5'b10101 :
reg_rt_o = reg_r21;
5'b10110 :
reg_rt_o = reg_r22;
5'b10111 :
reg_rt_o = reg_r23;
5'b11000 :
reg_rt_o = reg_r24;
5'b11001 :
reg_rt_o = reg_r25;
5'b11010 :
reg_rt_o = reg_r26;
5'b11011 :
reg_rt_o = reg_r27;
5'b11100 :
reg_rt_o = reg_r28;
5'b11101 :
reg_rt_o = reg_r29;
5'b11110 :
reg_rt_o = reg_r30;
5'b11111 :
reg_rt_o = reg_r31;
default :
reg_rt_o = 32'h00000000;
endcase
end
end
else
begin
// Asynchronous Register read (Rs & Rd)
always @ *
begin
case (rs_i)
5'b00000 :
reg_rs_o = 32'h00000000;
5'b00001 :
reg_rs_o = reg_r1_sp;
5'b00010 :
reg_rs_o = reg_r2_fp;
5'b00011 :
reg_rs_o = reg_r3;
5'b00100 :
reg_rs_o = reg_r4;
5'b00101 :
reg_rs_o = reg_r5;
5'b00110 :
reg_rs_o = reg_r6;
5'b00111 :
reg_rs_o = reg_r7;
5'b01000 :
reg_rs_o = reg_r8;
5'b01001 :
reg_rs_o = reg_r9_lr;
5'b01010 :
reg_rs_o = reg_r10;
5'b01011 :
reg_rs_o = reg_r11;
5'b01100 :
reg_rs_o = reg_r12;
5'b01101 :
reg_rs_o = reg_r13;
5'b01110 :
reg_rs_o = reg_r14;
5'b01111 :
reg_rs_o = reg_r15;
default :
reg_rs_o = 32'h00000000;
endcase
 
case (rt_i)
5'b00000 :
reg_rt_o = 32'h00000000;
5'b00001 :
reg_rt_o = reg_r1_sp;
5'b00010 :
reg_rt_o = reg_r2_fp;
5'b00011 :
reg_rt_o = reg_r3;
5'b00100 :
reg_rt_o = reg_r4;
5'b00101 :
reg_rt_o = reg_r5;
5'b00110 :
reg_rt_o = reg_r6;
5'b00111 :
reg_rt_o = reg_r7;
5'b01000 :
reg_rt_o = reg_r8;
5'b01001 :
reg_rt_o = reg_r9_lr;
5'b01010 :
reg_rt_o = reg_r10;
5'b01011 :
reg_rt_o = reg_r11;
5'b01100 :
reg_rt_o = reg_r12;
5'b01101 :
reg_rt_o = reg_r13;
5'b01110 :
reg_rt_o = reg_r14;
5'b01111 :
reg_rt_o = reg_r15;
default :
reg_rt_o = 32'h00000000;
endcase
end
end
endgenerate
 
endmodule
/rtl/cpu/altor32_lfu.v
0,0 → 1,137
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module: Load Forwarding Unit
//-----------------------------------------------------------------
module altor32_lfu
(
// Opcode
input [7:0] opcode_i /*verilator public*/,
 
// Memory load result
input [31:0] mem_result_i /*verilator public*/,
input [1:0] mem_offset_i /*verilator public*/,
 
// Result
output reg [31:0] load_result_o /*verilator public*/,
output reg load_insn_o /*verilator public*/
);
 
//-------------------------------------------------------------------
// Load forwarding unit
//-------------------------------------------------------------------
always @ *
begin
load_result_o = 32'h00000000;
load_insn_o = 1'b0;
 
case (opcode_i)
 
`INST_OR32_LBS: // l.lbs
begin
case (mem_offset_i)
2'b00 : load_result_o[7:0] = mem_result_i[31:24];
2'b01 : load_result_o[7:0] = mem_result_i[23:16];
2'b10 : load_result_o[7:0] = mem_result_i[15:8];
2'b11 : load_result_o[7:0] = mem_result_i[7:0];
default : ;
endcase
// Sign extend LB
if (load_result_o[7] == 1'b1)
load_result_o[31:8] = 24'hFFFFFF;
 
load_insn_o = 1'b1;
end
`INST_OR32_LBZ: // l.lbz
begin
case (mem_offset_i)
2'b00 : load_result_o[7:0] = mem_result_i[31:24];
2'b01 : load_result_o[7:0] = mem_result_i[23:16];
2'b10 : load_result_o[7:0] = mem_result_i[15:8];
2'b11 : load_result_o[7:0] = mem_result_i[7:0];
default : ;
endcase
 
load_insn_o = 1'b1;
end
 
`INST_OR32_LHS: // l.lhs
begin
case (mem_offset_i)
2'b00 : load_result_o[15:0] = mem_result_i[31:16];
2'b10 : load_result_o[15:0] = mem_result_i[15:0];
default : ;
endcase
 
// Sign extend LH
if (load_result_o[15] == 1'b1)
load_result_o[31:16] = 16'hFFFF;
 
load_insn_o = 1'b1;
end
`INST_OR32_LHZ: // l.lhz
begin
case (mem_offset_i)
2'b00 : load_result_o[15:0] = mem_result_i[31:16];
2'b10 : load_result_o[15:0] = mem_result_i[15:0];
default : ;
endcase
 
load_insn_o = 1'b1;
end
 
`INST_OR32_LWZ, `INST_OR32_LWS: // l.lwz l.lws
begin
load_result_o = mem_result_i;
load_insn_o = 1'b1;
end
 
default :
;
endcase
end
 
endmodule
/rtl/cpu/altor32_fetch.v
0,0 → 1,186
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//`define CONF_FETCH_DEBUG
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Instruction Fetch
//-----------------------------------------------------------------
module altor32_fetch
(
// General
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
 
// Instruction Fetch
output fetch_o /*verilator public*/,
output [31:0] pc_o /*verilator public*/,
input [31:0] data_i /*verilator public*/,
input data_valid_i/*verilator public*/,
 
// Branch target
input branch_i /*verilator public*/,
input [31:0] branch_pc_i /*verilator public*/,
input stall_i /*verilator public*/,
 
// Decoded opcode
output [31:0] opcode_o /*verilator public*/,
output [31:0] opcode_pc_o /*verilator public*/,
output opcode_valid_o /*verilator public*/,
 
// Decoded register details
output [4:0] ra_o /*verilator public*/,
output [4:0] rb_o /*verilator public*/,
output [4:0] rd_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter BOOT_VECTOR = 32'h00000000;
parameter CACHE_LINE_SIZE_WIDTH = 5; /* 5-bits -> 32 entries */
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [31:0] r_pc;
reg r_rd;
reg [31:0] r_last_opcode;
reg [31:0] r_last_pc;
reg r_last_valid;
reg [31:0] d_pc;
 
//-------------------------------------------------------------------
// Next PC state machine
//-------------------------------------------------------------------
reg [31:0] v_pc;
 
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i)
begin
r_pc <= BOOT_VECTOR + `VECTOR_RESET;
d_pc <= BOOT_VECTOR + `VECTOR_RESET;
r_rd <= 1'b1;
end
else
begin
r_rd <= 1'b0;
d_pc <= pc_o;
 
// Branch - Next PC = branch target + 4
if (branch_i)
begin
r_pc <= branch_pc_i + 4;
end
// Stall - rollback to previous PC + 4
else if (stall_i)
begin
r_pc <= d_pc + 4;
end
// Normal sequential execution (and instruction is ready)
else if (data_valid_i)
begin
v_pc = r_pc + 4;
 
// New cache line?
if (v_pc[CACHE_LINE_SIZE_WIDTH-1:0] == {CACHE_LINE_SIZE_WIDTH{1'b0}})
begin
// Start fetch of next line
r_rd <= 1'b1;
end
 
r_pc <= v_pc;
end
end
end
 
//-------------------------------------------------------------------
// Pipeline storage of last PC/opcode passed to exec stage
//-------------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
begin
if (rst_i)
begin
r_last_opcode <= 32'b0;
r_last_pc <= 32'b0;
r_last_valid <= 1'b0;
 
end
else
begin
// Record last valid instruction passed to exec stage
if (!stall_i | !data_valid_i)
begin
r_last_pc <= opcode_pc_o;
r_last_opcode <= opcode_o;
r_last_valid <= opcode_valid_o;
end
end
end
 
//-------------------------------------------------------------------
// Assignments
//-------------------------------------------------------------------
 
// Instruction Fetch
assign pc_o = stall_i ? d_pc : (branch_i ? branch_pc_i : (~data_valid_i ? d_pc : r_pc));
assign fetch_o = branch_i ? 1'b1 : r_rd;
 
// Opcode output
assign opcode_valid_o = stall_i ? r_last_valid : (data_valid_i & !branch_i);
assign opcode_o = stall_i ? r_last_opcode : (opcode_valid_o ? data_i : 32'b0);
assign opcode_pc_o = stall_i ? r_last_pc : (opcode_valid_o ? d_pc : 32'b0);
 
// If simulation, RA = 03 if NOP instruction
`ifdef SIMULATION
wire [7:0] v_fetch_inst = {2'b00, opcode_o[31:26]};
wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP);
assign ra_o = v_is_nop ? 5'd3 : opcode_o[20:16];
`else
assign ra_o = opcode_o[20:16];
`endif
 
assign rb_o = opcode_o[15:11];
assign rd_o = opcode_o[25:21];
 
endmodule
/rtl/cpu/altor32_regfile_xil.v
0,0 → 1,145
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module - Xilinx register file (async read)
//-----------------------------------------------------------------
module altor32_regfile_xil
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter SUPPORT_32REGS = "ENABLED";
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [4:0] addr_write;
wire [31:0] data_out1;
wire [31:0] data_out2;
reg write_enable;
wire [31:0] data_out1a;
wire [31:0] data_out1b;
wire [31:0] data_out2a;
wire [31:0] data_out2b;
wire wea;
wire web;
 
//-----------------------------------------------------------------
// Async Read Process
//-----------------------------------------------------------------
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i)
begin
// Read Rs
if (rs_i == 5'b00000)
reg_rs_o <= 32'h00000000;
else
reg_rs_o <= data_out1;
 
// Read Rt
if (rt_i == 5'b00000)
reg_rt_o <= 32'h00000000;
else
reg_rt_o <= data_out2;
 
// Write enabled?
addr_write <= rd_i[4:0];
if ((rd_i != 5'b00000) & (wr_i == 1'b1))
write_enable <= 1'b1;
else
write_enable <= 1'b0;
end
 
//-----------------------------------------------------------------
// Register File (using RAM16X1D )
//-----------------------------------------------------------------
 
// Registers 0 - 15
generate
begin
genvar i;
for (i=0;i<32;i=i+1)
begin : reg_loop1
RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1a[i]), .SPO(/* open */));
RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1b[i]), .SPO(/* open */));
end
end
endgenerate
 
// Registers 16 - 31
generate
if (SUPPORT_32REGS == "ENABLED")
begin
genvar i;
for (i=0;i<32;i=i+1)
begin : reg_loop2
RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2a[i]), .SPO(/* open */));
RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2b[i]), .SPO(/* open */));
end
end
else
begin
assign data_out2a = 32'h00000000;
assign data_out2b = 32'h00000000;
end
endgenerate
 
//-----------------------------------------------------------------
// Combinatorial Assignments
//-----------------------------------------------------------------
assign data_out1 = (rs_i[4] == 1'b0) ? data_out1a : data_out1b;
assign data_out2 = (rt_i[4] == 1'b0) ? data_out2a : data_out2b;
assign wea = (write_enable & ~ (addr_write[4]));
assign web = (write_enable & addr_write[4]);
 
endmodule
/rtl/cpu/altor32_ram_dp.v
0,0 → 1,94
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module: altor32_ram_dp - Dual port RAM (used in cache)
//-----------------------------------------------------------------
module altor32_ram_dp
(
input aclk_i /*verilator public*/,
output [(WIDTH - 1):0] adat_o /*verilator public*/,
input [(WIDTH - 1):0] adat_i /*verilator public*/,
input [(SIZE - 1):0] aadr_i /*verilator public*/,
input awr_i /*verilator public*/,
 
input bclk_i /*verilator public*/,
output [(WIDTH - 1):0] bdat_o /*verilator public*/,
input [(WIDTH - 1):0] bdat_i /*verilator public*/,
input [(SIZE - 1):0] badr_i /*verilator public*/,
input bwr_i /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] WIDTH = 8;
parameter [31:0] SIZE = 14;
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
/* verilator lint_off MULTIDRIVEN */
reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/;
/* verilator lint_on MULTIDRIVEN */
 
reg [(SIZE - 1):0] rd_addr_a;
reg [(SIZE - 1):0] rd_addr_b;
 
//-----------------------------------------------------------------
// Processes
//-----------------------------------------------------------------
always @ (posedge aclk_i)
begin
if (awr_i == 1'b1)
ram[aadr_i] <= adat_i;
rd_addr_a <= aadr_i;
end
always @ (posedge bclk_i)
begin
if (bwr_i == 1'b1)
ram[badr_i] <= bdat_i;
rd_addr_b <= badr_i;
end
 
//-------------------------------------------------------------------
// Combinatorial
//-------------------------------------------------------------------
assign adat_o = ram[rd_addr_a];
assign bdat_o = ram[rd_addr_b];
 
endmodule
/rtl/cpu/altor32_lsu.v
0,0 → 1,159
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
 
//-----------------------------------------------------------------
// Module: Load / Store Unit
//-----------------------------------------------------------------
module altor32_lsu
(
// Current instruction
input opcode_valid_i /*verilator public*/,
input [7:0] opcode_i /*verilator public*/,
 
// Load / Store pending
input load_pending_i /*verilator public*/,
input store_pending_i /*verilator public*/,
 
// Load dest register
input [4:0] rd_load_i /*verilator public*/,
 
// Load insn in WB stage
input load_wb_i /*verilator public*/,
 
// Memory status
input mem_access_i /*verilator public*/,
input mem_ack_i /*verilator public*/,
 
// Load / store still pending
output reg load_pending_o /*verilator public*/,
output reg store_pending_o /*verilator public*/,
 
// Insert load result into pipeline
output reg write_result_o /*verilator public*/,
 
// Stall pipeline due load / store / insert
output reg stall_o /*verilator public*/
);
 
//-------------------------------------------------------------------
// Outstanding memory access logic
//-------------------------------------------------------------------
reg v_inst_load;
reg v_inst_store;
 
always @ *
begin
load_pending_o = load_pending_i;
store_pending_o = store_pending_i;
stall_o = 1'b0;
write_result_o = 1'b0;
 
// Is this instruction a load or store?
v_inst_load = is_load_operation(opcode_i);
v_inst_store = is_store_operation(opcode_i);
 
// Store operation just completed?
if (store_pending_o & mem_ack_i & ~mem_access_i)
begin
`ifdef CONF_CORE_DEBUG
$display(" Store operation now completed");
`endif
store_pending_o = 1'b0;
end
 
// Load just completed (and result ready in-time for writeback stage)?
if (load_pending_o & mem_ack_i & ~mem_access_i & load_wb_i)
begin
// Load complete
load_pending_o = 1'b0;
 
`ifdef CONF_CORE_DEBUG
$display(" Load operation completed in writeback stage");
`endif
end
// Load just completed (later than writeback stage)?
else if (load_pending_o & mem_ack_i & ~mem_access_i)
begin
`ifdef CONF_CORE_DEBUG
$display(" Load operation completed later than writeback stage");
`endif
// Valid target register?
if (rd_load_i != 5'b00000)
begin
`ifdef CONF_CORE_DEBUG
$display(" Load result now ready for R%d", rd_load_i);
`endif
// Stall instruction and write load result to pipeline
stall_o = opcode_valid_i;
write_result_o = 1'b1;
end
else
begin
`ifdef CONF_CORE_DEBUG
$display(" Load result ready but not needed");
`endif
end
// Load complete
load_pending_o = 1'b0;
end
 
// If load or store in progress (and this instruction is valid)
if ((load_pending_o | store_pending_o) & opcode_valid_i)
begin
// Load or store whilst memory bus busy
if (v_inst_load | v_inst_store)
begin
`ifdef CONF_CORE_DEBUG
$display(" Data bus already busy, stall (load_pending_o=%d, store_pending_o=%d)", load_pending_o, store_pending_o);
`endif
// Stall!
stall_o = 1'b1;
end
end
end
 
`include "altor32_funcs.v"
 
endmodule
/rtl/sim/test_image.lst
0,0 → 1,4630
 
firmware.elf: file format elf32-or1k
 
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00002fd8 10000000 10000000 00002000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000008 10002fd8 10002fd8 00004fd8 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00001030 10002fe0 10002fe0 00004fe0 2**2
ALLOC
3 .debug_info 00002151 00000000 00000000 00004fe0 2**0
CONTENTS, READONLY, DEBUGGING
4 .debug_abbrev 00000b63 00000000 00000000 00007131 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_loc 00000fc6 00000000 00000000 00007c94 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_aranges 00000140 00000000 00000000 00008c5a 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_ranges 000000b8 00000000 00000000 00008d9a 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_line 00000ad7 00000000 00000000 00008e52 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_str 000006d5 00000000 00000000 00009929 2**0
CONTENTS, READONLY, DEBUGGING
10 .comment 00000029 00000000 00000000 00009ffe 2**0
CONTENTS, READONLY
11 .debug_frame 0000039c 00000000 00000000 0000a028 2**2
CONTENTS, READONLY, DEBUGGING
 
Disassembly of section .text:
 
10000000 <_start-0x100>:
...
 
10000100 <_start>:
10000100: 18 80 10 00 l.movhi r4,0x1000
10000104: a8 24 40 00 l.ori r1,r4,0x4000
10000108: 18 80 10 00 l.movhi r4,0x1000
1000010c: a8 84 2f e0 l.ori r4,r4,0x2fe0
10000110: 18 a0 10 00 l.movhi r5,0x1000
10000114: a8 a5 40 10 l.ori r5,r5,0x4010
 
10000118 <BSS_CLEAR>:
10000118: d4 04 00 00 l.sw 0(r4),r0
1000011c: e4 a4 28 00 l.sfleu r4,r5
10000120: 9c 84 00 04 l.addi r4,r4,4
10000124: 13 ff ff fd l.bf 10000118 <BSS_CLEAR>
10000128: 15 00 00 00 l.nop 0x0
1000012c: 04 00 03 b5 l.jal 10001000 <main>
10000130: 15 00 00 00 l.nop 0x0
...
 
10000400 <vector_extint>:
10000400: 24 00 00 00 l.rfe
10000404: 15 00 00 00 l.nop 0x0
...
10000ffc: 15 00 00 00 l.nop 0x0
 
10001000 <main>:
int main(void)
{
int res;
 
// Setup printf to serial port
printf_register(serial_putchar);
10001000: 18 60 10 00 l.movhi r3,0x1000
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int main(void)
{
10001004: d7 e1 4f fc l.sw -4(r1),r9
10001008: d7 e1 0f f8 l.sw -8(r1),r1
int res;
 
// Setup printf to serial port
printf_register(serial_putchar);
1000100c: a8 63 1a 54 l.ori r3,r3,0x1a54
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int main(void)
{
10001010: 9c 21 ff f8 l.addi r1,r1,-8
int res;
 
// Setup printf to serial port
printf_register(serial_putchar);
10001014: 04 00 01 32 l.jal 100014dc <printf_register>
 
// Run test
res = test();
10001018: 04 00 03 35 l.jal 10001cec <test>
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
 
// No error?
if (exit_code == 0)
1000101c: bc 2b 00 00 l.sfnei r11,0
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001020: a5 6b 00 ff l.andi r11,r11,0xff
10001024: a8 2b 00 00 l.ori r1,r11,0x0
 
// No error?
if (exit_code == 0)
10001028: 0c 00 00 06 l.bnf 10001040 <main+0x40>
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000102c: c8 00 00 00 lf.add.s r0,r0,r0
 
// Exit with result
exit(res);
}
10001030: 9c 21 00 08 l.addi r1,r1,8
10001034: 85 21 ff fc l.lwz r9,-4(r1)
10001038: 84 21 ff f8 l.lwz r1,-8(r1)
1000103c: 44 00 48 00 l.jr r9
 
// No error?
if (exit_code == 0)
{
// Trap instruction
__asm__ __volatile__ ( "\t l.trap 0 ");
10001040: 21 00 00 00 l.trap 0x0
10001044: 03 ff ff fb l.j 10001030 <main+0x30>
 
10001048 <exception_register_fault_handler>:
static volatile int in_interrupt = 0;
 
//-----------------------------------------------------------------
// exception_register:
//-----------------------------------------------------------------
void exception_register_fault_handler(void (*func)(void)) { func_fault = func; }
10001048: 18 80 10 00 l.movhi r4,0x1000
1000104c: d7 e1 0f fc l.sw -4(r1),r1
10001050: a8 84 2f f0 l.ori r4,r4,0x2ff0
10001054: 9c 21 ff fc l.addi r1,r1,-4
10001058: d4 04 18 00 l.sw 0(r4),r3
1000105c: 9c 21 00 04 l.addi r1,r1,4
10001060: 84 21 ff fc l.lwz r1,-4(r1)
10001064: 44 00 48 00 l.jr r9
 
10001068 <exception_register_break_handler>:
void exception_register_break_handler(void (*func)(void)) { func_break = func; }
10001068: 18 80 10 00 l.movhi r4,0x1000
1000106c: d7 e1 0f fc l.sw -4(r1),r1
10001070: a8 84 2f ec l.ori r4,r4,0x2fec
10001074: 9c 21 ff fc l.addi r1,r1,-4
10001078: d4 04 18 00 l.sw 0(r4),r3
1000107c: 9c 21 00 04 l.addi r1,r1,4
10001080: 84 21 ff fc l.lwz r1,-4(r1)
10001084: 44 00 48 00 l.jr r9
 
10001088 <exception_register_extint_handler>:
void exception_register_extint_handler(void (*func)(void)) { func_extint = func; }
10001088: 18 80 10 00 l.movhi r4,0x1000
1000108c: d7 e1 0f fc l.sw -4(r1),r1
10001090: a8 84 2f e8 l.ori r4,r4,0x2fe8
10001094: 9c 21 ff fc l.addi r1,r1,-4
10001098: d4 04 18 00 l.sw 0(r4),r3
1000109c: 9c 21 00 04 l.addi r1,r1,4
100010a0: 84 21 ff fc l.lwz r1,-4(r1)
100010a4: 44 00 48 00 l.jr r9
 
100010a8 <exception_register_syscall_handler>:
void exception_register_syscall_handler(void (*func)(void)) { func_syscall = func; }
100010a8: 18 80 10 00 l.movhi r4,0x1000
100010ac: d7 e1 0f fc l.sw -4(r1),r1
100010b0: a8 84 2f e4 l.ori r4,r4,0x2fe4
100010b4: 9c 21 ff fc l.addi r1,r1,-4
100010b8: d4 04 18 00 l.sw 0(r4),r3
100010bc: 9c 21 00 04 l.addi r1,r1,4
100010c0: 84 21 ff fc l.lwz r1,-4(r1)
100010c4: 44 00 48 00 l.jr r9
 
100010c8 <cpu_handle_irq>:
 
//-----------------------------------------------------------------
// cpu_handle_irq:
//-----------------------------------------------------------------
void cpu_handle_irq(unsigned cause)
{
100010c8: d7 e1 17 f4 l.sw -12(r1),r2
int recursive_int = (in_interrupt != 0);
100010cc: 18 40 10 00 l.movhi r2,0x1000
 
in_interrupt = 1;
100010d0: 9c 80 00 01 l.addi r4,r0,1
//-----------------------------------------------------------------
// cpu_handle_irq:
//-----------------------------------------------------------------
void cpu_handle_irq(unsigned cause)
{
int recursive_int = (in_interrupt != 0);
100010d4: a8 42 2f e0 l.ori r2,r2,0x2fe0
 
//-----------------------------------------------------------------
// cpu_handle_irq:
//-----------------------------------------------------------------
void cpu_handle_irq(unsigned cause)
{
100010d8: d7 e1 77 f8 l.sw -8(r1),r14
100010dc: d7 e1 4f fc l.sw -4(r1),r9
100010e0: d7 e1 0f f0 l.sw -16(r1),r1
int recursive_int = (in_interrupt != 0);
100010e4: 85 c2 00 00 l.lwz r14,0(r2)
 
in_interrupt = 1;
 
switch (cause)
100010e8: bc 43 00 08 l.sfgtui r3,8
//-----------------------------------------------------------------
void cpu_handle_irq(unsigned cause)
{
int recursive_int = (in_interrupt != 0);
 
in_interrupt = 1;
100010ec: d4 02 20 00 l.sw 0(r2),r4
 
//-----------------------------------------------------------------
// cpu_handle_irq:
//-----------------------------------------------------------------
void cpu_handle_irq(unsigned cause)
{
100010f0: 9c 21 ff e4 l.addi r1,r1,-28
int recursive_int = (in_interrupt != 0);
 
in_interrupt = 1;
 
switch (cause)
100010f4: 10 00 00 71 l.bf 100012b8 <cpu_handle_irq+0x1f0>
100010f8: 18 80 10 00 l.movhi r4,0x1000
100010fc: b8 63 00 02 l.slli r3,r3,0x2
10001100: a8 84 2b 00 l.ori r4,r4,0x2b00
10001104: e0 63 20 00 l.add r3,r3,r4
10001108: 84 63 00 00 l.lwz r3,0(r3)
1000110c: 44 00 18 00 l.jr r3
case EXCEPTION_DIV:
panic("DIV!");
break;
 
case EXCEPTION_UDIV:
panic("UDIV!");
10001110: 18 60 10 00 l.movhi r3,0x1000
10001114: a8 63 2c e4 l.ori r3,r3,0x2ce4
10001118: d4 01 18 00 l.sw 0(r1),r3
1000111c: 18 60 10 00 l.movhi r3,0x1000
10001120: a8 63 2c 9a l.ori r3,r3,0x2c9a
10001124: d4 01 18 04 l.sw 4(r1),r3
10001128: 9c 60 00 6e l.addi r3,r0,110
break;
 
default:
panic("UNKNOWN");
1000112c: d4 01 18 08 l.sw 8(r1),r3
10001130: 18 60 10 00 l.movhi r3,0x1000
10001134: a8 63 2c 74 l.ori r3,r3,0x2c74
10001138: 04 00 02 2b l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
1000113c: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001140: c8 00 00 00 lf.add.s r0,r0,r0
break;
}
 
assert(recursive_int == 0);
10001144: bc 0e 00 00 l.sfeqi r14,0
10001148: 10 00 00 0e l.bf 10001180 <cpu_handle_irq+0xb8>
1000114c: 18 60 10 00 l.movhi r3,0x1000
10001150: a8 63 2c f6 l.ori r3,r3,0x2cf6
10001154: d4 01 18 00 l.sw 0(r1),r3
10001158: 18 60 10 00 l.movhi r3,0x1000
1000115c: a8 63 2c 9a l.ori r3,r3,0x2c9a
10001160: d4 01 18 04 l.sw 4(r1),r3
10001164: 9c 60 00 76 l.addi r3,r0,118
10001168: d4 01 18 08 l.sw 8(r1),r3
1000116c: 18 60 10 00 l.movhi r3,0x1000
10001170: a8 63 2c 74 l.ori r3,r3,0x2c74
10001174: 04 00 02 1c l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001178: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000117c: c8 00 00 00 lf.add.s r0,r0,r0
 
in_interrupt = 0;
10001180: 9c 60 00 00 l.addi r3,r0,0
10001184: d4 02 18 00 l.sw 0(r2),r3
}
10001188: 9c 21 00 1c l.addi r1,r1,28
1000118c: 85 21 ff fc l.lwz r9,-4(r1)
10001190: 84 21 ff f0 l.lwz r1,-16(r1)
10001194: 84 41 ff f4 l.lwz r2,-12(r1)
10001198: 85 c1 ff f8 l.lwz r14,-8(r1)
1000119c: 44 00 48 00 l.jr r9
in_interrupt = 1;
 
switch (cause)
{
case EXCEPTION_SYSCALL:
if (func_syscall)
100011a0: 18 60 10 00 l.movhi r3,0x1000
100011a4: a8 63 2f e4 l.ori r3,r3,0x2fe4
100011a8: 84 63 00 00 l.lwz r3,0(r3)
100011ac: bc 03 00 00 l.sfeqi r3,0
100011b0: 10 00 00 4a l.bf 100012d8 <cpu_handle_irq+0x210>
panic("EXT_INT!");
break;
 
case EXCEPTION_FAULT:
if (func_fault)
func_fault();
100011b4: 48 00 18 00 l.jalr r3
100011b8: 03 ff ff e3 l.j 10001144 <cpu_handle_irq+0x7c>
else
panic("SYSCALL!");
break;
 
case EXCEPTION_BREAK:
if (func_break)
100011bc: 18 60 10 00 l.movhi r3,0x1000
100011c0: a8 63 2f ec l.ori r3,r3,0x2fec
100011c4: 84 63 00 00 l.lwz r3,0(r3)
100011c8: bc 03 00 00 l.sfeqi r3,0
100011cc: 0f ff ff fa l.bnf 100011b4 <cpu_handle_irq+0xec>
func_break();
else
panic("BREAK!");
100011d0: 18 60 10 00 l.movhi r3,0x1000
100011d4: a8 63 2c b0 l.ori r3,r3,0x2cb0
100011d8: d4 01 18 00 l.sw 0(r1),r3
100011dc: 18 60 10 00 l.movhi r3,0x1000
100011e0: a8 63 2c 9a l.ori r3,r3,0x2c9a
100011e4: d4 01 18 04 l.sw 4(r1),r3
100011e8: 9c 60 00 50 l.addi r3,r0,80
100011ec: 03 ff ff d0 l.j 1000112c <cpu_handle_irq+0x64>
break;
 
case EXCEPTION_EXTINT:
if (func_extint)
100011f0: 18 60 10 00 l.movhi r3,0x1000
100011f4: a8 63 2f e8 l.ori r3,r3,0x2fe8
100011f8: 84 63 00 00 l.lwz r3,0(r3)
100011fc: bc 03 00 00 l.sfeqi r3,0
10001200: 0f ff ff ed l.bnf 100011b4 <cpu_handle_irq+0xec>
func_extint();
else
panic("EXT_INT!");
10001204: 18 60 10 00 l.movhi r3,0x1000
10001208: a8 63 2c b9 l.ori r3,r3,0x2cb9
1000120c: d4 01 18 00 l.sw 0(r1),r3
10001210: 18 60 10 00 l.movhi r3,0x1000
10001214: a8 63 2c 9a l.ori r3,r3,0x2c9a
10001218: d4 01 18 04 l.sw 4(r1),r3
1000121c: 9c 60 00 57 l.addi r3,r0,87
10001220: 03 ff ff c3 l.j 1000112c <cpu_handle_irq+0x64>
break;
 
case EXCEPTION_FAULT:
if (func_fault)
10001224: 18 60 10 00 l.movhi r3,0x1000
10001228: a8 63 2f f0 l.ori r3,r3,0x2ff0
1000122c: 84 63 00 00 l.lwz r3,0(r3)
10001230: bc 03 00 00 l.sfeqi r3,0
10001234: 0f ff ff e0 l.bnf 100011b4 <cpu_handle_irq+0xec>
func_fault();
else
panic("FAULT");
10001238: 18 60 10 00 l.movhi r3,0x1000
1000123c: a8 63 2c c4 l.ori r3,r3,0x2cc4
10001240: d4 01 18 00 l.sw 0(r1),r3
10001244: 18 60 10 00 l.movhi r3,0x1000
10001248: a8 63 2c 9a l.ori r3,r3,0x2c9a
1000124c: d4 01 18 04 l.sw 4(r1),r3
10001250: 9c 60 00 5e l.addi r3,r0,94
10001254: 03 ff ff b6 l.j 1000112c <cpu_handle_irq+0x64>
break;
 
case EXCEPTION_MULT:
panic("MULT!");
10001258: 18 60 10 00 l.movhi r3,0x1000
1000125c: a8 63 2c cc l.ori r3,r3,0x2ccc
10001260: d4 01 18 00 l.sw 0(r1),r3
10001264: 18 60 10 00 l.movhi r3,0x1000
10001268: a8 63 2c 9a l.ori r3,r3,0x2c9a
1000126c: d4 01 18 04 l.sw 4(r1),r3
10001270: 9c 60 00 62 l.addi r3,r0,98
10001274: 03 ff ff ae l.j 1000112c <cpu_handle_irq+0x64>
break;
 
case EXCEPTION_UMULT:
panic("UMULT!");
10001278: 18 60 10 00 l.movhi r3,0x1000
1000127c: a8 63 2c d4 l.ori r3,r3,0x2cd4
10001280: d4 01 18 00 l.sw 0(r1),r3
10001284: 18 60 10 00 l.movhi r3,0x1000
10001288: a8 63 2c 9a l.ori r3,r3,0x2c9a
1000128c: d4 01 18 04 l.sw 4(r1),r3
10001290: 9c 60 00 66 l.addi r3,r0,102
10001294: 03 ff ff a6 l.j 1000112c <cpu_handle_irq+0x64>
break;
 
case EXCEPTION_DIV:
panic("DIV!");
10001298: 18 60 10 00 l.movhi r3,0x1000
1000129c: a8 63 2c dd l.ori r3,r3,0x2cdd
100012a0: d4 01 18 00 l.sw 0(r1),r3
100012a4: 18 60 10 00 l.movhi r3,0x1000
100012a8: a8 63 2c 9a l.ori r3,r3,0x2c9a
100012ac: d4 01 18 04 l.sw 4(r1),r3
100012b0: 9c 60 00 6a l.addi r3,r0,106
100012b4: 03 ff ff 9e l.j 1000112c <cpu_handle_irq+0x64>
case EXCEPTION_UDIV:
panic("UDIV!");
break;
 
default:
panic("UNKNOWN");
100012b8: 18 60 10 00 l.movhi r3,0x1000
100012bc: a8 63 2c ec l.ori r3,r3,0x2cec
100012c0: d4 01 18 00 l.sw 0(r1),r3
100012c4: 18 60 10 00 l.movhi r3,0x1000
100012c8: a8 63 2c 9a l.ori r3,r3,0x2c9a
100012cc: d4 01 18 04 l.sw 4(r1),r3
100012d0: 9c 60 00 72 l.addi r3,r0,114
100012d4: 03 ff ff 96 l.j 1000112c <cpu_handle_irq+0x64>
{
case EXCEPTION_SYSCALL:
if (func_syscall)
func_syscall();
else
panic("SYSCALL!");
100012d8: 18 60 10 00 l.movhi r3,0x1000
100012dc: a8 63 2c 8f l.ori r3,r3,0x2c8f
100012e0: d4 01 18 00 l.sw 0(r1),r3
100012e4: 18 60 10 00 l.movhi r3,0x1000
100012e8: a8 63 2c 9a l.ori r3,r3,0x2c9a
100012ec: d4 01 18 04 l.sw 4(r1),r3
100012f0: 9c 60 00 49 l.addi r3,r0,73
100012f4: 03 ff ff 8e l.j 1000112c <cpu_handle_irq+0x64>
 
100012f8 <outnum.isra.1>:
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
100012f8: 18 e0 38 39 l.movhi r7,0x3839
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
100012fc: d7 e1 17 dc l.sw -36(r1),r2
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
10001300: a9 07 41 42 l.ori r8,r7,0x4142
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
10001304: d7 e1 a7 e8 l.sw -24(r1),r20
10001308: d7 e1 b7 ec l.sw -20(r1),r22
1000130c: d7 e1 4f fc l.sw -4(r1),r9
10001310: d7 e1 0f d8 l.sw -40(r1),r1
10001314: d7 e1 77 e0 l.sw -32(r1),r14
10001318: d7 e1 97 e4 l.sw -28(r1),r18
1000131c: d7 e1 c7 f0 l.sw -16(r1),r24
10001320: d7 e1 d7 f4 l.sw -12(r1),r26
10001324: d7 e1 e7 f8 l.sw -8(r1),r28
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
10001328: 18 40 34 35 l.movhi r2,0x3435
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
1000132c: 9c 21 ff 90 l.addi r1,r1,-112
const char *digits;
unsigned long num;
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
10001330: ac c4 00 0a l.xori r6,r4,10
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
10001334: a8 42 36 37 l.ori r2,r2,0x3637
10001338: d4 01 40 08 l.sw 8(r1),r8
1000133c: 19 00 43 44 l.movhi r8,0x4344
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
10001340: aa 84 00 00 l.ori r20,r4,0x0
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
10001344: a9 08 45 46 l.ori r8,r8,0x4546
const char *digits;
unsigned long num;
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
10001348: e1 60 30 02 l.sub r11,r0,r6
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
1000134c: 18 80 30 31 l.movhi r4,0x3031
10001350: d4 01 10 04 l.sw 4(r1),r2
const char ldigits[] = "0123456789abcdef";
10001354: d4 01 10 18 l.sw 24(r1),r2
10001358: 18 40 63 64 l.movhi r2,0x6364
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
1000135c: a8 84 32 33 l.ori r4,r4,0x3233
const char ldigits[] = "0123456789abcdef";
10001360: a8 e7 61 62 l.ori r7,r7,0x6162
const char *digits;
unsigned long num;
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
10001364: e0 cb 30 04 l.or r6,r11,r6
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
10001368: d4 01 40 0c l.sw 12(r1),r8
const char ldigits[] = "0123456789abcdef";
1000136c: a8 42 65 66 l.ori r2,r2,0x6566
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
{
char* cp;
int negative;
char outbuf[32];
const char udigits[] = "0123456789ABCDEF";
10001370: 9d 00 00 00 l.addi r8,r0,0
10001374: d4 01 20 00 l.sw 0(r1),r4
10001378: d8 01 40 10 l.sb 16(r1),r8
const char ldigits[] = "0123456789abcdef";
1000137c: d4 01 20 14 l.sw 20(r1),r4
10001380: d4 01 38 1c l.sw 28(r1),r7
10001384: d4 01 10 20 l.sw 32(r1),r2
10001388: d8 01 40 24 l.sb 36(r1),r8
const char *digits;
unsigned long num;
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
1000138c: bd 86 00 00 l.sfltsi r6,0
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
10001390: aa c5 00 00 l.ori r22,r5,0x0
const char *digits;
unsigned long num;
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
10001394: 10 00 00 03 l.bf 100013a0 <outnum.isra.1+0xa8>
10001398: bd 63 00 00 l.sfgesi r3,0
1000139c: 0c 00 00 4d l.bnf 100014d0 <outnum.isra.1+0x1d8>
negative = 1;
num = -(n);
}
else{
num = (n);
100013a0: a8 43 00 00 l.ori r2,r3,0x0
negative = 0;
100013a4: 9f 80 00 00 l.addi r28,r0,0
}
 
if (par->uppercase)
100013a8: 84 76 00 18 l.lwz r3,24(r22)
digits = udigits;
100013ac: ab 41 00 00 l.ori r26,r1,0x0
else{
num = (n);
negative = 0;
}
 
if (par->uppercase)
100013b0: bc 03 00 00 l.sfeqi r3,0
100013b4: 0c 00 00 02 l.bnf 100013bc <outnum.isra.1+0xc4>
digits = udigits;
else
digits = ldigits;
100013b8: 9f 41 00 14 l.addi r26,r1,20
100013bc: 9f 01 00 28 l.addi r24,r1,40
100013c0: a9 d8 00 00 l.ori r14,r24,0x0
100013c4: 00 00 00 02 l.j 100013cc <outnum.isra.1+0xd4>
100013c8: a9 d2 00 00 l.ori r14,r18,0x0
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % base)];
100013cc: a8 62 00 00 l.ori r3,r2,0x0
100013d0: a8 94 00 00 l.ori r4,r20,0x0
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
100013d4: 9e 4e 00 01 l.addi r18,r14,1
digits = ldigits;
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % base)];
100013d8: 04 00 05 52 l.jal 10002920 <__umodsi3>
100013dc: e1 7a 58 00 l.add r11,r26,r11
} while ((num /= base) > 0);
100013e0: a8 62 00 00 l.ori r3,r2,0x0
digits = ldigits;
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % base)];
100013e4: 8d 6b 00 00 l.lbz r11,0(r11)
} while ((num /= base) > 0);
100013e8: a8 94 00 00 l.ori r4,r20,0x0
digits = ldigits;
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % base)];
100013ec: d8 0e 58 00 l.sb 0(r14),r11
} while ((num /= base) > 0);
100013f0: 04 00 05 43 l.jal 100028fc <__udivsi3>
100013f4: bc 0b 00 00 l.sfeqi r11,0
100013f8: a8 4b 00 00 l.ori r2,r11,0x0
100013fc: 0f ff ff f3 l.bnf 100013c8 <outnum.isra.1+0xd0>
if (negative)
10001400: bc 1c 00 00 l.sfeqi r28,0
10001404: 10 00 00 04 l.bf 10001414 <outnum.isra.1+0x11c>
*cp++ = '-';
10001408: 9c 40 00 2d l.addi r2,r0,45
1000140c: 9e 4e 00 02 l.addi r18,r14,2
10001410: d8 0e 10 01 l.sb 1(r14),r2
*cp-- = 0;
10001414: 9d 00 00 00 l.addi r8,r0,0
10001418: 9d d2 ff ff l.addi r14,r18,-1
1000141c: d8 12 40 00 l.sb 0(r18),r8
const char * s;
 
if(!str)
return 0;
 
for(s = str; *s; ++ s)
10001420: 90 81 00 28 l.lbs r4,40(r1)
10001424: bc 04 00 00 l.sfeqi r4,0
10001428: 10 00 00 08 l.bf 10001448 <outnum.isra.1+0x150>
1000142c: 9c 41 00 29 l.addi r2,r1,41
10001430: a8 82 00 00 l.ori r4,r2,0x0
10001434: 9c 42 00 01 l.addi r2,r2,1
10001438: 90 62 ff ff l.lbs r3,-1(r2)
1000143c: bc 03 00 00 l.sfeqi r3,0
10001440: 0f ff ff fc l.bnf 10001430 <outnum.isra.1+0x138>
10001444: e0 84 c0 02 l.sub r4,r4,r24
*cp++ = '-';
*cp-- = 0;
 
/* Move the converted number to the buffer and */
/* add in the padding where needed. */
par->len = strlen(outbuf);
10001448: d4 16 20 00 l.sw 0(r22),r4
#ifdef PRINTF_ENABLE_PADDING
padding(buf, !(par->left_flag), par);
#endif
count = 0;
while (cp >= outbuf && count++ < par->max_len)
1000144c: e4 6e c0 00 l.sfgeu r14,r24
10001450: 0c 00 00 14 l.bnf 100014a0 <outnum.isra.1+0x1a8>
10001454: 84 56 00 1c l.lwz r2,28(r22)
10001458: bd a2 00 00 l.sflesi r2,0
1000145c: 10 00 00 11 l.bf 100014a0 <outnum.isra.1+0x1a8>
10001460: 1a 80 10 00 l.movhi r20,0x1000
/* This routine moves a number to the output buffer */
/* as directed by the padding and positioning flags. */
/* */
//----------------------------------------------------
#if defined PRINTF_DEC_PRINT || defined PRINTF_HEX_PRINT
static void outnum( struct vbuf *buf, const long n, const long base, params_t *par)
10001464: e2 52 c0 02 l.sub r18,r18,r24
par->len = strlen(outbuf);
#ifdef PRINTF_ENABLE_PADDING
padding(buf, !(par->left_flag), par);
#endif
count = 0;
while (cp >= outbuf && count++ < par->max_len)
10001468: 9c 40 00 01 l.addi r2,r0,1
1000146c: aa 94 2f f4 l.ori r20,r20,0x2ff4
10001470: 00 00 00 05 l.j 10001484 <outnum.isra.1+0x18c>
10001474: 84 96 00 1c l.lwz r4,28(r22)
10001478: e5 a4 10 00 l.sfles r4,r2
1000147c: a8 43 00 00 l.ori r2,r3,0x0
10001480: 10 00 00 08 l.bf 100014a0 <outnum.isra.1+0x1a8>
vbuf_putchar(buf, *cp--);
10001484: 90 6e 00 00 l.lbs r3,0(r14)
10001488: 85 74 00 00 l.lwz r11,0(r20)
1000148c: 9d ce ff ff l.addi r14,r14,-1
10001490: 48 00 58 00 l.jalr r11
par->len = strlen(outbuf);
#ifdef PRINTF_ENABLE_PADDING
padding(buf, !(par->left_flag), par);
#endif
count = 0;
while (cp >= outbuf && count++ < par->max_len)
10001494: e4 02 90 00 l.sfeq r2,r18
10001498: 9c 62 00 01 l.addi r3,r2,1
1000149c: 0f ff ff f6 l.bnf 10001474 <outnum.isra.1+0x17c>
vbuf_putchar(buf, *cp--);
#ifdef PRINTF_ENABLE_PADDING
padding(buf, par->left_flag, par);
#endif
}
100014a0: 9c 21 00 70 l.addi r1,r1,112
100014a4: 85 21 ff fc l.lwz r9,-4(r1)
100014a8: 84 21 ff d8 l.lwz r1,-40(r1)
100014ac: 84 41 ff dc l.lwz r2,-36(r1)
100014b0: 85 c1 ff e0 l.lwz r14,-32(r1)
100014b4: 86 41 ff e4 l.lwz r18,-28(r1)
100014b8: 86 81 ff e8 l.lwz r20,-24(r1)
100014bc: 86 c1 ff ec l.lwz r22,-20(r1)
100014c0: 87 01 ff f0 l.lwz r24,-16(r1)
100014c4: 87 41 ff f4 l.lwz r26,-12(r1)
100014c8: 87 81 ff f8 l.lwz r28,-8(r1)
100014cc: 44 00 48 00 l.jr r9
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
negative = 1;
num = -(n);
100014d0: e0 40 18 02 l.sub r2,r0,r3
unsigned long num;
int count;
 
/* Check if number is negative */
if (base == 10 && n < 0L) {
negative = 1;
100014d4: 9f 80 00 01 l.addi r28,r0,1
100014d8: 03 ff ff b4 l.j 100013a8 <outnum.isra.1+0xb0>
 
100014dc <printf_register>:
//----------------------------------------------------
// printf_register: Assign printf output function
//----------------------------------------------------
void printf_register(FP_OUTCHAR f)
{
_stdout = f;
100014dc: 18 80 10 00 l.movhi r4,0x1000
}
//----------------------------------------------------
// printf_register: Assign printf output function
//----------------------------------------------------
void printf_register(FP_OUTCHAR f)
{
100014e0: d7 e1 0f fc l.sw -4(r1),r1
_stdout = f;
100014e4: a8 84 2f f4 l.ori r4,r4,0x2ff4
}
//----------------------------------------------------
// printf_register: Assign printf output function
//----------------------------------------------------
void printf_register(FP_OUTCHAR f)
{
100014e8: 9c 21 ff fc l.addi r1,r1,-4
_stdout = f;
100014ec: d4 04 18 00 l.sw 0(r4),r3
}
100014f0: 9c 21 00 04 l.addi r1,r1,4
100014f4: 84 21 ff fc l.lwz r1,-4(r1)
100014f8: 44 00 48 00 l.jr r9
 
100014fc <puts>:
#endif
//----------------------------------------------------
// puts:
//----------------------------------------------------
int puts( const char * str )
{
100014fc: d7 e1 77 f8 l.sw -8(r1),r14
if (!_stdout)
10001500: 19 c0 10 00 l.movhi r14,0x1000
#endif
//----------------------------------------------------
// puts:
//----------------------------------------------------
int puts( const char * str )
{
10001504: d7 e1 17 f4 l.sw -12(r1),r2
if (!_stdout)
10001508: a9 ce 2f f4 l.ori r14,r14,0x2ff4
#endif
//----------------------------------------------------
// puts:
//----------------------------------------------------
int puts( const char * str )
{
1000150c: d7 e1 4f fc l.sw -4(r1),r9
if (!_stdout)
10001510: 85 6e 00 00 l.lwz r11,0(r14)
#endif
//----------------------------------------------------
// puts:
//----------------------------------------------------
int puts( const char * str )
{
10001514: d7 e1 0f f0 l.sw -16(r1),r1
if (!_stdout)
10001518: bc 0b 00 00 l.sfeqi r11,0
#endif
//----------------------------------------------------
// puts:
//----------------------------------------------------
int puts( const char * str )
{
1000151c: 9c 21 ff f0 l.addi r1,r1,-16
10001520: a8 43 00 00 l.ori r2,r3,0x0
if (!_stdout)
10001524: 10 00 00 12 l.bf 1000156c <puts+0x70>
return -1;
 
while (*str)
10001528: 90 63 00 00 l.lbs r3,0(r3)
1000152c: bc 03 00 00 l.sfeqi r3,0
10001530: 10 00 00 07 l.bf 1000154c <puts+0x50>
_stdout(*str++);
10001534: 9c 42 00 01 l.addi r2,r2,1
10001538: 48 00 58 00 l.jalr r11
int puts( const char * str )
{
if (!_stdout)
return -1;
 
while (*str)
1000153c: 90 62 00 00 l.lbs r3,0(r2)
10001540: bc 03 00 00 l.sfeqi r3,0
10001544: 85 6e 00 00 l.lwz r11,0(r14)
10001548: 0f ff ff fb l.bnf 10001534 <puts+0x38>
_stdout(*str++);
 
return _stdout('\n');
1000154c: 9c 60 00 0a l.addi r3,r0,10
10001550: 48 00 58 00 l.jalr r11
}
10001554: 9c 21 00 10 l.addi r1,r1,16
10001558: 85 21 ff fc l.lwz r9,-4(r1)
1000155c: 84 21 ff f0 l.lwz r1,-16(r1)
10001560: 84 41 ff f4 l.lwz r2,-12(r1)
10001564: 85 c1 ff f8 l.lwz r14,-8(r1)
10001568: 44 00 48 00 l.jr r9
// puts:
//----------------------------------------------------
int puts( const char * str )
{
if (!_stdout)
return -1;
1000156c: 9d 60 ff ff l.addi r11,r0,-1
10001570: 03 ff ff f9 l.j 10001554 <puts+0x58>
 
10001574 <putchar>:
}
//----------------------------------------------------
// putchar:
//----------------------------------------------------
int putchar( int c )
{
10001574: d7 e1 17 f8 l.sw -8(r1),r2
10001578: a8 43 00 00 l.ori r2,r3,0x0
if (!_stdout)
1000157c: 18 60 10 00 l.movhi r3,0x1000
}
//----------------------------------------------------
// putchar:
//----------------------------------------------------
int putchar( int c )
{
10001580: d7 e1 4f fc l.sw -4(r1),r9
if (!_stdout)
10001584: a8 63 2f f4 l.ori r3,r3,0x2ff4
}
//----------------------------------------------------
// putchar:
//----------------------------------------------------
int putchar( int c )
{
10001588: d7 e1 0f f4 l.sw -12(r1),r1
if (!_stdout)
1000158c: 85 63 00 00 l.lwz r11,0(r3)
}
//----------------------------------------------------
// putchar:
//----------------------------------------------------
int putchar( int c )
{
10001590: 9c 21 ff f4 l.addi r1,r1,-12
if (!_stdout)
10001594: bc 0b 00 00 l.sfeqi r11,0
10001598: 10 00 00 0a l.bf 100015c0 <putchar+0x4c>
return -1;
 
_stdout((char)c);
1000159c: b8 62 00 18 l.slli r3,r2,0x18
100015a0: b8 63 00 98 l.srai r3,r3,0x18
100015a4: 48 00 58 00 l.jalr r11
 
return c;
100015a8: a9 62 00 00 l.ori r11,r2,0x0
}
100015ac: 9c 21 00 0c l.addi r1,r1,12
100015b0: 85 21 ff fc l.lwz r9,-4(r1)
100015b4: 84 21 ff f4 l.lwz r1,-12(r1)
100015b8: 84 41 ff f8 l.lwz r2,-8(r1)
100015bc: 44 00 48 00 l.jr r9
// putchar:
//----------------------------------------------------
int putchar( int c )
{
if (!_stdout)
return -1;
100015c0: 9d 60 ff ff l.addi r11,r0,-1
100015c4: 03 ff ff fa l.j 100015ac <putchar+0x38>
 
100015c8 <vbuf_printf>:
/* added easily by following the examples shown for */
/* the supported formats. */
/* */
//----------------------------------------------------
int vbuf_printf(struct vbuf *buf, const char* ctrl1, va_list argp)
{
100015c8: d7 e1 97 e0 l.sw -32(r1),r18
100015cc: d7 e1 f7 f8 l.sw -8(r1),r30
100015d0: d7 e1 4f fc l.sw -4(r1),r9
100015d4: d7 e1 0f d4 l.sw -44(r1),r1
100015d8: d7 e1 17 d8 l.sw -40(r1),r2
100015dc: d7 e1 77 dc l.sw -36(r1),r14
100015e0: d7 e1 a7 e4 l.sw -28(r1),r20
100015e4: d7 e1 b7 e8 l.sw -24(r1),r22
100015e8: d7 e1 c7 ec l.sw -20(r1),r24
100015ec: d7 e1 d7 f0 l.sw -16(r1),r26
100015f0: d7 e1 e7 f4 l.sw -12(r1),r28
100015f4: ab c4 00 00 l.ori r30,r4,0x0
params_t par;
 
char ch;
char* ctrl = (char*)ctrl1;
 
for ( ; *ctrl; ctrl++)
100015f8: 90 64 00 00 l.lbs r3,0(r4)
100015fc: bc 23 00 00 l.sfnei r3,0
/* added easily by following the examples shown for */
/* the supported formats. */
/* */
//----------------------------------------------------
int vbuf_printf(struct vbuf *buf, const char* ctrl1, va_list argp)
{
10001600: 9c 21 ff b4 l.addi r1,r1,-76
10001604: aa 45 00 00 l.ori r18,r5,0x0
params_t par;
 
char ch;
char* ctrl = (char*)ctrl1;
 
for ( ; *ctrl; ctrl++)
10001608: 0c 00 00 77 l.bnf 100017e4 <vbuf_printf+0x21c>
{
/* move format string chars to buffer until a */
/* format control is found. */
if (*ctrl != '%')
{
vbuf_putchar(buf, *ctrl);
1000160c: 19 c0 10 00 l.movhi r14,0x1000
}
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
par.pad_character = ' ';
par.num2=32767;
10001610: 9f 40 7f ff l.addi r26,r0,32767
{
/* move format string chars to buffer until a */
/* format control is found. */
if (*ctrl != '%')
{
vbuf_putchar(buf, *ctrl);
10001614: a9 ce 2f f4 l.ori r14,r14,0x2ff4
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
par.pad_character = ' ';
par.num2=32767;
par.max_len = 10;
10001618: 9f 00 00 0a l.addi r24,r0,10
1000161c: 00 00 00 08 l.j 1000163c <vbuf_printf+0x74>
{
/* move format string chars to buffer until a */
/* format control is found. */
if (*ctrl != '%')
{
vbuf_putchar(buf, *ctrl);
10001620: 85 6e 00 00 l.lwz r11,0(r14)
continue;
10001624: ab 9e 00 00 l.ori r28,r30,0x0
{
/* move format string chars to buffer until a */
/* format control is found. */
if (*ctrl != '%')
{
vbuf_putchar(buf, *ctrl);
10001628: 48 00 58 00 l.jalr r11
params_t par;
 
char ch;
char* ctrl = (char*)ctrl1;
 
for ( ; *ctrl; ctrl++)
1000162c: 90 7c 00 01 l.lbs r3,1(r28)
10001630: bc 03 00 00 l.sfeqi r3,0
10001634: 9f dc 00 01 l.addi r30,r28,1
10001638: 10 00 00 6b l.bf 100017e4 <vbuf_printf+0x21c>
{
/* move format string chars to buffer until a */
/* format control is found. */
if (*ctrl != '%')
1000163c: bc 03 00 25 l.sfeqi r3,37
10001640: 0f ff ff f8 l.bnf 10001620 <vbuf_printf+0x58>
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
par.pad_character = ' ';
par.num2=32767;
par.max_len = 10;
10001644: 90 be 00 01 l.lbs r5,1(r30)
continue;
}
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
par.pad_character = ' ';
10001648: 9c 60 00 20 l.addi r3,r0,32
vbuf_putchar(buf, *ctrl);
continue;
}
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
1000164c: 9c 40 00 00 l.addi r2,r0,0
par.pad_character = ' ';
10001650: d8 01 18 0c l.sb 12(r1),r3
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
10001654: a4 65 00 ff l.andi r3,r5,0xff
vbuf_putchar(buf, *ctrl);
continue;
}
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
10001658: d4 01 10 10 l.sw 16(r1),r2
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
1000165c: 9c 83 ff d0 l.addi r4,r3,-48
vbuf_putchar(buf, *ctrl);
continue;
}
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
10001660: d4 01 10 14 l.sw 20(r1),r2
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
10001664: a4 84 00 ff l.andi r4,r4,0xff
}
 
/* initialize all the flags for this format. */
dot_flag = long_flag = par.left_flag = par.do_padding = 0;
par.pad_character = ' ';
par.num2=32767;
10001668: d4 01 d0 08 l.sw 8(r1),r26
par.max_len = 10;
1000166c: d4 01 c0 1c l.sw 28(r1),r24
 
try_next:
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
10001670: bc 44 00 09 l.sfgtui r4,9
10001674: 9f 9e 00 01 l.addi r28,r30,1
}
ctrl--;
goto try_next;
}
 
par.uppercase = (ch >= 'A' && ch <= 'Z') ? 1 : 0;
10001678: 9e 80 00 01 l.addi r20,r0,1
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
1000167c: 10 00 00 1a l.bf 100016e4 <vbuf_printf+0x11c>
{
if (dot_flag)
10001680: bc 02 00 00 l.sfeqi r2,0
10001684: 10 00 00 9a l.bf 100018ec <vbuf_printf+0x324>
10001688: 9c c0 00 00 l.addi r6,r0,0
1000168c: 9c 85 ff d0 l.addi r4,r5,-48
10001690: 00 00 00 02 l.j 10001698 <vbuf_printf+0xd0>
char* cp;
 
n = 0;
cp = *linep;
while (((*cp) >= '0' && (*cp) <= '9'))
n = n*10 + ((*cp++) - '0');
10001694: ab 83 00 00 l.ori r28,r3,0x0
10001698: b8 e6 00 03 l.slli r7,r6,0x3
1000169c: 9c 7c 00 01 l.addi r3,r28,1
100016a0: e0 c6 30 00 l.add r6,r6,r6
long n;
char* cp;
 
n = 0;
cp = *linep;
while (((*cp) >= '0' && (*cp) <= '9'))
100016a4: 90 a3 00 00 l.lbs r5,0(r3)
n = n*10 + ((*cp++) - '0');
100016a8: e0 c6 38 00 l.add r6,r6,r7
100016ac: e0 c6 20 00 l.add r6,r6,r4
long n;
char* cp;
 
n = 0;
cp = *linep;
while (((*cp) >= '0' && (*cp) <= '9'))
100016b0: 9c 85 ff d0 l.addi r4,r5,-48
100016b4: a4 e4 00 ff l.andi r7,r4,0xff
100016b8: bc 47 00 09 l.sfgtui r7,9
100016bc: 0f ff ff f6 l.bnf 10001694 <vbuf_printf+0xcc>
100016c0: a8 83 00 00 l.ori r4,r3,0x0
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
{
if (dot_flag)
par.num2 = getnum(&ctrl);
100016c4: d4 01 30 08 l.sw 8(r1),r6
par.pad_character = '0';
 
par.num1 = getnum(&ctrl);
par.do_padding = 1;
}
ctrl--;
100016c8: 9f c3 ff ff l.addi r30,r3,-1
100016cc: ab 84 00 00 l.ori r28,r4,0x0
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
 
if ((ch >= '0' && ch <= '9'))
100016d0: a4 65 00 ff l.andi r3,r5,0xff
100016d4: 9c 83 ff d0 l.addi r4,r3,-48
100016d8: a4 84 00 ff l.andi r4,r4,0xff
100016dc: bc 44 00 09 l.sfgtui r4,9
100016e0: 0f ff ff e8 l.bnf 10001680 <vbuf_printf+0xb8>
}
ctrl--;
goto try_next;
}
 
par.uppercase = (ch >= 'A' && ch <= 'Z') ? 1 : 0;
100016e4: 9c 63 ff bf l.addi r3,r3,-65
100016e8: 9c 80 00 01 l.addi r4,r0,1
100016ec: a4 63 00 ff l.andi r3,r3,0xff
100016f0: bc a3 00 19 l.sfleui r3,25
100016f4: 10 00 00 02 l.bf 100016fc <vbuf_printf+0x134>
100016f8: 9c 80 00 00 l.addi r4,r0,0
100016fc: d4 01 20 18 l.sw 24(r1),r4
 
switch ((par.uppercase ? ch + 32: ch))
10001700: bc 04 00 00 l.sfeqi r4,0
10001704: a8 65 00 00 l.ori r3,r5,0x0
10001708: 10 00 00 02 l.bf 10001710 <vbuf_printf+0x148>
1000170c: 9c 65 00 20 l.addi r3,r5,32
10001710: 9c 63 ff db l.addi r3,r3,-37
10001714: bc 43 00 53 l.sfgtui r3,83
10001718: 13 ff ff c5 l.bf 1000162c <vbuf_printf+0x64>
1000171c: 18 80 10 00 l.movhi r4,0x1000
10001720: b8 63 00 02 l.slli r3,r3,0x2
10001724: a8 84 2b 24 l.ori r4,r4,0x2b24
10001728: e0 63 20 00 l.add r3,r3,r4
1000172c: 84 63 00 00 l.lwz r3,0(r3)
10001730: 44 00 18 00 l.jr r3
}
continue;
#endif
#ifdef PRINTF_STR_PRINT
case 's':
outs(buf, va_arg( argp, char*), &par);
10001734: 86 d2 00 00 l.lwz r22,0(r18)
10001738: 9e 52 00 04 l.addi r18,r18,4
//----------------------------------------------------
static int strlen(const char * str)
{
const char * s;
 
if(!str)
1000173c: bc 16 00 00 l.sfeqi r22,0
10001740: 10 00 00 a4 l.bf 100019d0 <vbuf_printf+0x408>
return 0;
 
for(s = str; *s; ++ s)
10001744: 90 56 00 00 l.lbs r2,0(r22)
10001748: bc 02 00 00 l.sfeqi r2,0
1000174c: 10 00 00 07 l.bf 10001768 <vbuf_printf+0x1a0>
10001750: a8 56 00 00 l.ori r2,r22,0x0
10001754: 9c 42 00 01 l.addi r2,r2,1
10001758: 90 62 00 00 l.lbs r3,0(r2)
1000175c: bc 03 00 00 l.sfeqi r3,0
10001760: 0f ff ff fd l.bnf 10001754 <vbuf_printf+0x18c>
10001764: e0 42 b0 02 l.sub r2,r2,r22
//----------------------------------------------------
#ifdef PRINTF_STR_PRINT
static void outs( struct vbuf *buf, char* lp, params_t *par)
{
/* pad on left if needed */
par->len = strlen( lp);
10001768: d4 01 10 00 l.sw 0(r1),r2
#ifdef PRINTF_ENABLE_PADDING
padding(buf, !(par->left_flag), par);
#endif
 
/* Move string to the buffer */
while (*lp && (par->num2)--)
1000176c: 90 56 00 00 l.lbs r2,0(r22)
10001770: bc 02 00 00 l.sfeqi r2,0
10001774: 10 00 00 16 l.bf 100017cc <vbuf_printf+0x204>
10001778: 84 41 00 08 l.lwz r2,8(r1)
1000177c: aa 96 00 00 l.ori r20,r22,0x0
10001780: 9c 62 ff ff l.addi r3,r2,-1
10001784: bc 22 00 00 l.sfnei r2,0
10001788: d4 01 18 08 l.sw 8(r1),r3
1000178c: 10 00 00 09 l.bf 100017b0 <vbuf_printf+0x1e8>
10001790: 00 00 00 92 l.j 100019d8 <vbuf_printf+0x410>
10001794: 84 61 00 08 l.lwz r3,8(r1)
10001798: 9e 94 00 01 l.addi r20,r20,1
1000179c: 9c 83 ff ff l.addi r4,r3,-1
100017a0: bc 03 00 00 l.sfeqi r3,0
100017a4: d4 01 20 08 l.sw 8(r1),r4
100017a8: 10 00 00 72 l.bf 10001970 <vbuf_printf+0x3a8>
vbuf_putchar(buf, *lp++);
100017ac: aa c2 00 00 l.ori r22,r2,0x0
100017b0: 90 74 00 00 l.lbs r3,0(r20)
100017b4: 85 6e 00 00 l.lwz r11,0(r14)
100017b8: 9c 56 00 01 l.addi r2,r22,1
100017bc: 48 00 58 00 l.jalr r11
#ifdef PRINTF_ENABLE_PADDING
padding(buf, !(par->left_flag), par);
#endif
 
/* Move string to the buffer */
while (*lp && (par->num2)--)
100017c0: 90 62 00 00 l.lbs r3,0(r2)
100017c4: bc 03 00 00 l.sfeqi r3,0
100017c8: 0f ff ff f3 l.bnf 10001794 <vbuf_printf+0x1cc>
const char * s;
 
if(!str)
return 0;
 
for(s = str; *s; ++ s)
100017cc: 9c 60 00 00 l.addi r3,r0,0
/* Move string to the buffer */
while (*lp && (par->num2)--)
vbuf_putchar(buf, *lp++);
 
/* Pad on right if needed */
par->len = strlen( lp);
100017d0: d4 01 18 00 l.sw 0(r1),r3
params_t par;
 
char ch;
char* ctrl = (char*)ctrl1;
 
for ( ; *ctrl; ctrl++)
100017d4: 90 7c 00 01 l.lbs r3,1(r28)
100017d8: bc 03 00 00 l.sfeqi r3,0
100017dc: 9f dc 00 01 l.addi r30,r28,1
100017e0: 0f ff ff 97 l.bnf 1000163c <vbuf_printf+0x74>
}
goto try_next;
}
 
return res;
}
100017e4: 9c 21 00 4c l.addi r1,r1,76
100017e8: 9d 60 00 00 l.addi r11,r0,0
100017ec: 85 21 ff fc l.lwz r9,-4(r1)
100017f0: 84 21 ff d4 l.lwz r1,-44(r1)
100017f4: 84 41 ff d8 l.lwz r2,-40(r1)
100017f8: 85 c1 ff dc l.lwz r14,-36(r1)
100017fc: 86 41 ff e0 l.lwz r18,-32(r1)
10001800: 86 81 ff e4 l.lwz r20,-28(r1)
10001804: 86 c1 ff e8 l.lwz r22,-24(r1)
10001808: 87 01 ff ec l.lwz r24,-20(r1)
1000180c: 87 41 ff f0 l.lwz r26,-16(r1)
10001810: 87 81 ff f4 l.lwz r28,-12(r1)
10001814: 87 c1 ff f8 l.lwz r30,-8(r1)
10001818: 44 00 48 00 l.jr r9
case 'x':
case 'p':
if (long_flag || ch == 'D')
{
par.max_len = sizeof(long) * 2;
outnum(buf, (long)va_arg(argp, long), 16L, &par);
1000181c: 84 72 00 00 l.lwz r3,0(r18)
#ifdef PRINTF_HEX_PRINT
case 'x':
case 'p':
if (long_flag || ch == 'D')
{
par.max_len = sizeof(long) * 2;
10001820: 9c 40 00 08 l.addi r2,r0,8
outnum(buf, (long)va_arg(argp, long), 16L, &par);
10001824: 9c 80 00 10 l.addi r4,r0,16
10001828: a8 a1 00 00 l.ori r5,r1,0x0
1000182c: 9e 52 00 04 l.addi r18,r18,4
#ifdef PRINTF_HEX_PRINT
case 'x':
case 'p':
if (long_flag || ch == 'D')
{
par.max_len = sizeof(long) * 2;
10001830: d4 01 10 1c l.sw 28(r1),r2
outnum(buf, (long)va_arg(argp, long), 16L, &par);
10001834: 07 ff fe b1 l.jal 100012f8 <outnum.isra.1>
10001838: 03 ff ff 7d l.j 1000162c <vbuf_printf+0x64>
1000183c: 9c 9e 00 02 l.addi r4,r30,2
10001840: 90 be 00 02 l.lbs r5,2(r30)
par.pad_character = ' ';
par.num2=32767;
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
10001844: ab dc 00 00 l.ori r30,r28,0x0
10001848: ab 84 00 00 l.ori r28,r4,0x0
1000184c: 03 ff ff a1 l.j 100016d0 <vbuf_printf+0x108>
{
outnum(buf, va_arg(argp, long), 10L, &par);
continue;
}
else {
outnum(buf, va_arg(argp, int), 10L, &par);
10001850: 84 72 00 00 l.lwz r3,0(r18)
10001854: 9c 80 00 0a l.addi r4,r0,10
10001858: a8 a1 00 00 l.ori r5,r1,0x0
1000185c: 9e 52 00 04 l.addi r18,r18,4
case 'x':
case 'p':
if (long_flag || ch == 'D')
{
par.max_len = sizeof(long) * 2;
outnum(buf, (long)va_arg(argp, long), 16L, &par);
10001860: 07 ff fe a6 l.jal 100012f8 <outnum.isra.1>
10001864: 03 ff ff 72 l.j 1000162c <vbuf_printf+0x64>
outs(buf, va_arg( argp, char*), &par);
continue;
#endif
#ifdef PRINTF_CHR_PRINT
case 'c':
vbuf_putchar(buf, va_arg( argp, int));
10001868: 90 72 00 03 l.lbs r3,3(r18)
1000186c: 85 6e 00 00 l.lwz r11,0(r14)
10001870: 9e 52 00 04 l.addi r18,r18,4
10001874: 48 00 58 00 l.jalr r11
continue;
10001878: 03 ff ff 6d l.j 1000162c <vbuf_printf+0x64>
#endif
case '\\':
switch (*ctrl) {
1000187c: bc 05 00 68 l.sfeqi r5,104
10001880: 10 00 00 50 l.bf 100019c0 <vbuf_printf+0x3f8>
10001884: bd 45 00 68 l.sfgtsi r5,104
10001888: 0c 00 00 30 l.bnf 10001948 <vbuf_printf+0x380>
1000188c: bc 05 00 6e l.sfeqi r5,110
10001890: 10 00 00 48 l.bf 100019b0 <vbuf_printf+0x3e8>
10001894: bc 05 00 72 l.sfeqi r5,114
10001898: 0c 00 00 42 l.bnf 100019a0 <vbuf_printf+0x3d8>
break;
case 'h':
vbuf_putchar(buf, 0x08);
break;
case 'r':
vbuf_putchar(buf, 0x0D);
1000189c: 85 6e 00 00 l.lwz r11,0(r14)
100018a0: 9c 60 00 0d l.addi r3,r0,13
100018a4: 48 00 58 00 l.jalr r11
break;
100018a8: 00 00 00 2d l.j 1000195c <vbuf_printf+0x394>
100018ac: 9c 9e 00 02 l.addi r4,r30,2
100018b0: 90 be 00 02 l.lbs r5,2(r30)
case '-':
par.left_flag = 1;
break;
 
case '.':
dot_flag = 1;
100018b4: 9c 40 00 01 l.addi r2,r0,1
par.pad_character = ' ';
par.num2=32767;
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
100018b8: ab dc 00 00 l.ori r30,r28,0x0
100018bc: ab 84 00 00 l.ori r28,r4,0x0
100018c0: 03 ff ff 84 l.j 100016d0 <vbuf_printf+0x108>
100018c4: 9c 9e 00 02 l.addi r4,r30,2
100018c8: 90 be 00 02 l.lbs r5,2(r30)
case '%':
vbuf_putchar(buf, '%');
continue;
 
case '-':
par.left_flag = 1;
100018cc: d4 01 a0 14 l.sw 20(r1),r20
par.pad_character = ' ';
par.num2=32767;
par.max_len = 10;
 
try_next:
ch = *(++ctrl);
100018d0: ab dc 00 00 l.ori r30,r28,0x0
100018d4: ab 84 00 00 l.ori r28,r4,0x0
100018d8: 03 ff ff 7e l.j 100016d0 <vbuf_printf+0x108>
par.uppercase = (ch >= 'A' && ch <= 'Z') ? 1 : 0;
 
switch ((par.uppercase ? ch + 32: ch))
{
case '%':
vbuf_putchar(buf, '%');
100018dc: 85 6e 00 00 l.lwz r11,0(r14)
100018e0: 9c 60 00 25 l.addi r3,r0,37
100018e4: 48 00 58 00 l.jalr r11
continue;
100018e8: 03 ff ff 51 l.j 1000162c <vbuf_printf+0x64>
if ((ch >= '0' && ch <= '9'))
{
if (dot_flag)
par.num2 = getnum(&ctrl);
else {
if (ch == '0')
100018ec: bc 25 00 30 l.sfnei r5,48
100018f0: 0c 00 00 14 l.bnf 10001940 <vbuf_printf+0x378>
static long getnum( char** linep)
{
long n;
char* cp;
 
n = 0;
100018f4: 9c c0 00 00 l.addi r6,r0,0
100018f8: 9c 85 ff d0 l.addi r4,r5,-48
100018fc: 00 00 00 02 l.j 10001904 <vbuf_printf+0x33c>
cp = *linep;
while (((*cp) >= '0' && (*cp) <= '9'))
n = n*10 + ((*cp++) - '0');
10001900: ab 83 00 00 l.ori r28,r3,0x0
10001904: b8 e6 00 03 l.slli r7,r6,0x3
10001908: 9c 7c 00 01 l.addi r3,r28,1
1000190c: e0 c6 30 00 l.add r6,r6,r6
long n;
char* cp;
 
n = 0;
cp = *linep;
while (((*cp) >= '0' && (*cp) <= '9'))
10001910: 90 a3 00 00 l.lbs r5,0(r3)
n = n*10 + ((*cp++) - '0');
10001914: e0 c6 38 00 l.add r6,r6,r7
10001918: e0 c6 20 00 l.add r6,r6,r4
long n;
char* cp;
 
n = 0;
cp = *linep;
while (((*cp) >= '0' && (*cp) <= '9'))
1000191c: 9c 85 ff d0 l.addi r4,r5,-48
10001920: a4 e4 00 ff l.andi r7,r4,0xff
10001924: bc 47 00 09 l.sfgtui r7,9
10001928: 0f ff ff f6 l.bnf 10001900 <vbuf_printf+0x338>
1000192c: a8 83 00 00 l.ori r4,r3,0x0
par.num2 = getnum(&ctrl);
else {
if (ch == '0')
par.pad_character = '0';
 
par.num1 = getnum(&ctrl);
10001930: d4 01 30 04 l.sw 4(r1),r6
par.do_padding = 1;
10001934: d4 01 a0 10 l.sw 16(r1),r20
}
ctrl--;
10001938: 9f c3 ff ff l.addi r30,r3,-1
1000193c: 03 ff ff 64 l.j 100016cc <vbuf_printf+0x104>
{
if (dot_flag)
par.num2 = getnum(&ctrl);
else {
if (ch == '0')
par.pad_character = '0';
10001940: d8 01 28 0c l.sb 12(r1),r5
10001944: 03 ff ff ec l.j 100018f4 <vbuf_printf+0x32c>
case 'c':
vbuf_putchar(buf, va_arg( argp, int));
continue;
#endif
case '\\':
switch (*ctrl) {
10001948: bc 05 00 61 l.sfeqi r5,97
1000194c: 0c 00 00 15 l.bnf 100019a0 <vbuf_printf+0x3d8>
case 'a':
vbuf_putchar(buf, 0x07);
10001950: 85 6e 00 00 l.lwz r11,0(r14)
10001954: 9c 60 00 07 l.addi r3,r0,7
10001958: 48 00 58 00 l.jalr r11
1000195c: 9c 9e 00 03 l.addi r4,r30,3
10001960: 90 be 00 03 l.lbs r5,3(r30)
10001964: ab 84 00 00 l.ori r28,r4,0x0
break;
default:
vbuf_putchar(buf, *ctrl);
break;
}
ctrl++;
10001968: 9f de 00 02 l.addi r30,r30,2
1000196c: 03 ff ff 59 l.j 100016d0 <vbuf_printf+0x108>
10001970: 90 76 00 01 l.lbs r3,1(r22)
const char * s;
 
if(!str)
return 0;
 
for(s = str; *s; ++ s)
10001974: bc 03 00 00 l.sfeqi r3,0
10001978: 9c 60 00 00 l.addi r3,r0,0
1000197c: 13 ff ff 95 l.bf 100017d0 <vbuf_printf+0x208>
10001980: a8 62 00 00 l.ori r3,r2,0x0
10001984: 9c 63 00 01 l.addi r3,r3,1
10001988: 90 83 00 00 l.lbs r4,0(r3)
1000198c: bc 04 00 00 l.sfeqi r4,0
10001990: 0f ff ff fd l.bnf 10001984 <vbuf_printf+0x3bc>
10001994: e0 63 10 02 l.sub r3,r3,r2
/* Move string to the buffer */
while (*lp && (par->num2)--)
vbuf_putchar(buf, *lp++);
 
/* Pad on right if needed */
par->len = strlen( lp);
10001998: d4 01 18 00 l.sw 0(r1),r3
1000199c: 03 ff ff 8e l.j 100017d4 <vbuf_printf+0x20c>
break;
case 'n':
vbuf_putchar(buf, 0x0A);
break;
default:
vbuf_putchar(buf, *ctrl);
100019a0: 90 7e 00 01 l.lbs r3,1(r30)
100019a4: 85 6e 00 00 l.lwz r11,0(r14)
100019a8: 48 00 58 00 l.jalr r11
break;
100019ac: 03 ff ff ec l.j 1000195c <vbuf_printf+0x394>
break;
case 'r':
vbuf_putchar(buf, 0x0D);
break;
case 'n':
vbuf_putchar(buf, 0x0A);
100019b0: 85 6e 00 00 l.lwz r11,0(r14)
100019b4: 9c 60 00 0a l.addi r3,r0,10
100019b8: 48 00 58 00 l.jalr r11
break;
100019bc: 03 ff ff e8 l.j 1000195c <vbuf_printf+0x394>
switch (*ctrl) {
case 'a':
vbuf_putchar(buf, 0x07);
break;
case 'h':
vbuf_putchar(buf, 0x08);
100019c0: 85 6e 00 00 l.lwz r11,0(r14)
100019c4: 9c 60 00 08 l.addi r3,r0,8
100019c8: 48 00 58 00 l.jalr r11
break;
100019cc: 03 ff ff e4 l.j 1000195c <vbuf_printf+0x394>
static int strlen(const char * str)
{
const char * s;
 
if(!str)
return 0;
100019d0: a8 56 00 00 l.ori r2,r22,0x0
100019d4: 03 ff ff 65 l.j 10001768 <vbuf_printf+0x1a0>
100019d8: 90 76 00 00 l.lbs r3,0(r22)
#ifdef PRINTF_ENABLE_PADDING
padding(buf, !(par->left_flag), par);
#endif
 
/* Move string to the buffer */
while (*lp && (par->num2)--)
100019dc: a8 56 00 00 l.ori r2,r22,0x0
100019e0: 03 ff ff e5 l.j 10001974 <vbuf_printf+0x3ac>
 
100019e4 <printf>:
{
int res = 0;
va_list argp;
struct vbuf buf;
 
if (_stdout && ctrl1)
100019e4: 18 a0 10 00 l.movhi r5,0x1000
}
//----------------------------------------------------
// printf: Console based printf
//----------------------------------------------------
int printf( const char* ctrl1, ... )
{
100019e8: d7 e1 4f fc l.sw -4(r1),r9
int res = 0;
va_list argp;
struct vbuf buf;
 
if (_stdout && ctrl1)
100019ec: a8 a5 2f f4 l.ori r5,r5,0x2ff4
}
//----------------------------------------------------
// printf: Console based printf
//----------------------------------------------------
int printf( const char* ctrl1, ... )
{
100019f0: d7 e1 0f f4 l.sw -12(r1),r1
int res = 0;
va_list argp;
struct vbuf buf;
 
if (_stdout && ctrl1)
100019f4: 85 65 00 00 l.lwz r11,0(r5)
}
//----------------------------------------------------
// printf: Console based printf
//----------------------------------------------------
int printf( const char* ctrl1, ... )
{
100019f8: d7 e1 17 f8 l.sw -8(r1),r2
int res = 0;
va_list argp;
struct vbuf buf;
 
if (_stdout && ctrl1)
100019fc: bc 0b 00 00 l.sfeqi r11,0
}
//----------------------------------------------------
// printf: Console based printf
//----------------------------------------------------
int printf( const char* ctrl1, ... )
{
10001a00: 9c 21 ff e4 l.addi r1,r1,-28
10001a04: a8 83 00 00 l.ori r4,r3,0x0
int res = 0;
va_list argp;
struct vbuf buf;
 
if (_stdout && ctrl1)
10001a08: 10 00 00 09 l.bf 10001a2c <printf+0x48>
{
va_start( argp, ctrl1);
// Setup target to be stdout function
buf.function = _stdout;
buf.buffer = 0;
10001a0c: 9c 40 00 00 l.addi r2,r0,0
buf.offset = 0;
buf.max_length = 0;
 
res = vbuf_printf(&buf, ctrl1, argp);
10001a10: a8 61 00 00 l.ori r3,r1,0x0
10001a14: 9c a1 00 1c l.addi r5,r1,28
if (_stdout && ctrl1)
{
va_start( argp, ctrl1);
// Setup target to be stdout function
buf.function = _stdout;
10001a18: d4 01 58 00 l.sw 0(r1),r11
buf.buffer = 0;
10001a1c: d4 01 10 04 l.sw 4(r1),r2
buf.offset = 0;
10001a20: d4 01 10 08 l.sw 8(r1),r2
buf.max_length = 0;
10001a24: d4 01 10 0c l.sw 12(r1),r2
 
res = vbuf_printf(&buf, ctrl1, argp);
10001a28: 07 ff fe e8 l.jal 100015c8 <vbuf_printf>
 
va_end( argp);
}
 
return res;
}
10001a2c: 9c 21 00 1c l.addi r1,r1,28
10001a30: 85 21 ff fc l.lwz r9,-4(r1)
10001a34: 84 21 ff f4 l.lwz r1,-12(r1)
10001a38: 84 41 ff f8 l.lwz r2,-8(r1)
10001a3c: 44 00 48 00 l.jr r9
 
10001a40 <serial_init>:
 
//-------------------------------------------------------------
// serial_init:
//-------------------------------------------------------------
void serial_init (void)
{
10001a40: d7 e1 0f fc l.sw -4(r1),r1
10001a44: 9c 21 ff fc l.addi r1,r1,-4
 
}
10001a48: 9c 21 00 04 l.addi r1,r1,4
10001a4c: 84 21 ff fc l.lwz r1,-4(r1)
10001a50: 44 00 48 00 l.jr r9
 
10001a54 <serial_putchar>:
//-------------------------------------------------------------
// serial_putchar: Write character to Serial Port (used by printf)
//-------------------------------------------------------------
int serial_putchar(char ch)
{
10001a54: b8 63 00 18 l.slli r3,r3,0x18
10001a58: d7 e1 17 f8 l.sw -8(r1),r2
10001a5c: d7 e1 4f fc l.sw -4(r1),r9
10001a60: b8 43 00 98 l.srai r2,r3,0x18
10001a64: d7 e1 0f f4 l.sw -12(r1),r1
10001a68: 9c 21 ff f4 l.addi r1,r1,-12
if (ch == '\n')
10001a6c: bc 22 00 0a l.sfnei r2,10
10001a70: 0c 00 00 10 l.bnf 10001ab0 <serial_putchar+0x5c>
serial_putchar('\r');
{
register char t1 asm ("r3") = ch;
10001a74: a8 62 00 00 l.ori r3,r2,0x0
asm volatile ("\tl.nop\t%0" : : "K" (0x0004), "r" (t1));
10001a78: 15 00 00 04 l.nop 0x4
}
 
UART_UDR = ch;
10001a7c: 18 60 12 00 l.movhi r3,0x1200
10001a80: a8 83 00 08 l.ori r4,r3,0x8
while (UART_USR & UART_TX_BUSY);
10001a84: a8 63 00 04 l.ori r3,r3,0x4
{
register char t1 asm ("r3") = ch;
asm volatile ("\tl.nop\t%0" : : "K" (0x0004), "r" (t1));
}
 
UART_UDR = ch;
10001a88: d4 04 10 00 l.sw 0(r4),r2
while (UART_USR & UART_TX_BUSY);
10001a8c: 85 63 00 00 l.lwz r11,0(r3)
10001a90: a5 6b 00 08 l.andi r11,r11,0x8
10001a94: bc 0b 00 00 l.sfeqi r11,0
10001a98: 0f ff ff fd l.bnf 10001a8c <serial_putchar+0x38>
 
return 0;
}
10001a9c: 9c 21 00 0c l.addi r1,r1,12
10001aa0: 85 21 ff fc l.lwz r9,-4(r1)
10001aa4: 84 21 ff f4 l.lwz r1,-12(r1)
10001aa8: 84 41 ff f8 l.lwz r2,-8(r1)
10001aac: 44 00 48 00 l.jr r9
// serial_putchar: Write character to Serial Port (used by printf)
//-------------------------------------------------------------
int serial_putchar(char ch)
{
if (ch == '\n')
serial_putchar('\r');
10001ab0: 9c 60 00 0d l.addi r3,r0,13
10001ab4: 07 ff ff e8 l.jal 10001a54 <serial_putchar>
10001ab8: 03 ff ff ef l.j 10001a74 <serial_putchar+0x20>
 
10001abc <serial_getchar>:
// serial_haschar:
//-------------------------------------------------------------
int serial_haschar()
{
#ifndef USE_NOP_PUTC
return (UART_USR & UART_RX_AVAIL);
10001abc: 18 60 12 00 l.movhi r3,0x1200
}
//-------------------------------------------------------------
// serial_getchar: Read character from Serial Port
//-------------------------------------------------------------
int serial_getchar (void)
{
10001ac0: d7 e1 0f fc l.sw -4(r1),r1
// serial_haschar:
//-------------------------------------------------------------
int serial_haschar()
{
#ifndef USE_NOP_PUTC
return (UART_USR & UART_RX_AVAIL);
10001ac4: a8 83 00 04 l.ori r4,r3,0x4
}
//-------------------------------------------------------------
// serial_getchar: Read character from Serial Port
//-------------------------------------------------------------
int serial_getchar (void)
{
10001ac8: 9c 21 ff fc l.addi r1,r1,-4
// serial_haschar:
//-------------------------------------------------------------
int serial_haschar()
{
#ifndef USE_NOP_PUTC
return (UART_USR & UART_RX_AVAIL);
10001acc: 84 84 00 00 l.lwz r4,0(r4)
10001ad0: a4 84 00 01 l.andi r4,r4,0x1
//-------------------------------------------------------------
int serial_getchar (void)
{
// Read character in from UART0 Recieve Buffer and return
#ifndef USE_NOP_PUTC
if (serial_haschar())
10001ad4: bc 04 00 00 l.sfeqi r4,0
10001ad8: 10 00 00 06 l.bf 10001af0 <serial_getchar+0x34>
return UART_UDR;
10001adc: a8 63 00 08 l.ori r3,r3,0x8
10001ae0: 85 63 00 00 l.lwz r11,0(r3)
else
#endif
return -1;
}
10001ae4: 9c 21 00 04 l.addi r1,r1,4
10001ae8: 84 21 ff fc l.lwz r1,-4(r1)
10001aec: 44 00 48 00 l.jr r9
#ifndef USE_NOP_PUTC
if (serial_haschar())
return UART_UDR;
else
#endif
return -1;
10001af0: 9d 60 ff ff l.addi r11,r0,-1
10001af4: 03 ff ff fc l.j 10001ae4 <serial_getchar+0x28>
 
10001af8 <serial_haschar>:
// serial_haschar:
//-------------------------------------------------------------
int serial_haschar()
{
#ifndef USE_NOP_PUTC
return (UART_USR & UART_RX_AVAIL);
10001af8: 18 60 12 00 l.movhi r3,0x1200
}
//-------------------------------------------------------------
// serial_haschar:
//-------------------------------------------------------------
int serial_haschar()
{
10001afc: d7 e1 0f fc l.sw -4(r1),r1
#ifndef USE_NOP_PUTC
return (UART_USR & UART_RX_AVAIL);
10001b00: a8 63 00 04 l.ori r3,r3,0x4
}
//-------------------------------------------------------------
// serial_haschar:
//-------------------------------------------------------------
int serial_haschar()
{
10001b04: 9c 21 ff fc l.addi r1,r1,-4
#ifndef USE_NOP_PUTC
return (UART_USR & UART_RX_AVAIL);
10001b08: 85 63 00 00 l.lwz r11,0(r3)
#else
return 0;
#endif
}
10001b0c: 9c 21 00 04 l.addi r1,r1,4
10001b10: a5 6b 00 01 l.andi r11,r11,0x1
10001b14: 84 21 ff fc l.lwz r1,-4(r1)
10001b18: 44 00 48 00 l.jr r9
 
10001b1c <serial_putstr>:
//-------------------------------------------------------------
// serial_putstr:
//-------------------------------------------------------------
void serial_putstr(char *str)
{
10001b1c: d7 e1 17 f8 l.sw -8(r1),r2
10001b20: d7 e1 4f fc l.sw -4(r1),r9
10001b24: d7 e1 0f f4 l.sw -12(r1),r1
10001b28: a8 43 00 00 l.ori r2,r3,0x0
while (*str)
10001b2c: 90 63 00 00 l.lbs r3,0(r3)
10001b30: bc 23 00 00 l.sfnei r3,0
}
//-------------------------------------------------------------
// serial_putstr:
//-------------------------------------------------------------
void serial_putstr(char *str)
{
10001b34: 9c 21 ff f4 l.addi r1,r1,-12
while (*str)
10001b38: 0c 00 00 06 l.bnf 10001b50 <serial_putstr+0x34>
serial_putchar(*str++);
10001b3c: 9c 42 00 01 l.addi r2,r2,1
10001b40: 07 ff ff c5 l.jal 10001a54 <serial_putchar>
//-------------------------------------------------------------
// serial_putstr:
//-------------------------------------------------------------
void serial_putstr(char *str)
{
while (*str)
10001b44: 90 62 00 00 l.lbs r3,0(r2)
10001b48: bc 03 00 00 l.sfeqi r3,0
10001b4c: 0f ff ff fc l.bnf 10001b3c <serial_putstr+0x20>
serial_putchar(*str++);
}
10001b50: 9c 21 00 0c l.addi r1,r1,12
10001b54: 85 21 ff fc l.lwz r9,-4(r1)
10001b58: 84 21 ff f4 l.lwz r1,-12(r1)
10001b5c: 84 41 ff f8 l.lwz r2,-8(r1)
10001b60: 44 00 48 00 l.jr r9
 
10001b64 <serial_putnum>:
//-------------------------------------------------------------
// serial_putnum:
//-------------------------------------------------------------
void serial_putnum( int n )
{
10001b64: d7 e1 17 e8 l.sw -24(r1),r2
char* cp;
int negative;
char outbuf[32];
const char digits[] = "0123456789ABCDEF";
10001b68: 18 40 30 31 l.movhi r2,0x3031
}
//-------------------------------------------------------------
// serial_putnum:
//-------------------------------------------------------------
void serial_putnum( int n )
{
10001b6c: d7 e1 4f fc l.sw -4(r1),r9
char* cp;
int negative;
char outbuf[32];
const char digits[] = "0123456789ABCDEF";
10001b70: a8 42 32 33 l.ori r2,r2,0x3233
}
//-------------------------------------------------------------
// serial_putnum:
//-------------------------------------------------------------
void serial_putnum( int n )
{
10001b74: d7 e1 0f e4 l.sw -28(r1),r1
10001b78: d7 e1 77 ec l.sw -20(r1),r14
10001b7c: d7 e1 97 f0 l.sw -16(r1),r18
10001b80: d7 e1 a7 f4 l.sw -12(r1),r20
10001b84: d7 e1 b7 f8 l.sw -8(r1),r22
10001b88: 9c 21 ff b0 l.addi r1,r1,-80
char outbuf[32];
const char digits[] = "0123456789ABCDEF";
unsigned long num;
 
/* Check if number is negative */
if (n < 0L) {
10001b8c: bd 63 00 00 l.sfgesi r3,0
void serial_putnum( int n )
{
char* cp;
int negative;
char outbuf[32];
const char digits[] = "0123456789ABCDEF";
10001b90: d4 01 10 00 l.sw 0(r1),r2
10001b94: 18 40 34 35 l.movhi r2,0x3435
10001b98: a8 42 36 37 l.ori r2,r2,0x3637
10001b9c: d4 01 10 04 l.sw 4(r1),r2
10001ba0: 18 40 38 39 l.movhi r2,0x3839
10001ba4: a8 42 41 42 l.ori r2,r2,0x4142
10001ba8: d4 01 10 08 l.sw 8(r1),r2
10001bac: 18 40 43 44 l.movhi r2,0x4344
10001bb0: a8 42 45 46 l.ori r2,r2,0x4546
10001bb4: d4 01 10 0c l.sw 12(r1),r2
10001bb8: 9c 40 00 00 l.addi r2,r0,0
10001bbc: d8 01 10 10 l.sb 16(r1),r2
unsigned long num;
 
/* Check if number is negative */
if (n < 0L) {
10001bc0: 0c 00 00 2e l.bnf 10001c78 <serial_putnum+0x114>
negative = 1;
num = -(n);
}
else{
num = (n);
10001bc4: a8 43 00 00 l.ori r2,r3,0x0
negative = 0;
10001bc8: 9e c0 00 00 l.addi r22,r0,0
10001bcc: 9e 81 00 14 l.addi r20,r1,20
10001bd0: a9 d4 00 00 l.ori r14,r20,0x0
10001bd4: 00 00 00 02 l.j 10001bdc <serial_putnum+0x78>
10001bd8: a9 d2 00 00 l.ori r14,r18,0x0
}
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % 10)];
10001bdc: a8 62 00 00 l.ori r3,r2,0x0
10001be0: 9c 80 00 0a l.addi r4,r0,10
serial_putchar(*str++);
}
//-------------------------------------------------------------
// serial_putnum:
//-------------------------------------------------------------
void serial_putnum( int n )
10001be4: 9e 4e 00 01 l.addi r18,r14,1
}
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % 10)];
10001be8: 04 00 03 4e l.jal 10002920 <__umodsi3>
10001bec: 9c 61 00 00 l.addi r3,r1,0
} while ((num /= 10) > 0);
10001bf0: 9c 80 00 0a l.addi r4,r0,10
}
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % 10)];
10001bf4: e1 63 58 00 l.add r11,r3,r11
} while ((num /= 10) > 0);
10001bf8: a8 62 00 00 l.ori r3,r2,0x0
}
/* Build number (backwards) in outbuf */
cp = outbuf;
do {
*cp++ = digits[(int)(num % 10)];
10001bfc: 8d 6b 00 00 l.lbz r11,0(r11)
10001c00: d8 0e 58 00 l.sb 0(r14),r11
} while ((num /= 10) > 0);
10001c04: 04 00 03 3e l.jal 100028fc <__udivsi3>
10001c08: bc 0b 00 00 l.sfeqi r11,0
10001c0c: a8 4b 00 00 l.ori r2,r11,0x0
10001c10: 0f ff ff f2 l.bnf 10001bd8 <serial_putnum+0x74>
if (negative)
10001c14: bc 16 00 00 l.sfeqi r22,0
10001c18: 10 00 00 04 l.bf 10001c28 <serial_putnum+0xc4>
*cp++ = '-';
10001c1c: 9c 40 00 2d l.addi r2,r0,45
10001c20: 9e 4e 00 02 l.addi r18,r14,2
10001c24: d8 0e 10 01 l.sb 1(r14),r2
*cp-- = 0;
10001c28: 9c 52 ff ff l.addi r2,r18,-1
10001c2c: 9c 60 00 00 l.addi r3,r0,0
while (cp >= outbuf)
10001c30: e4 62 a0 00 l.sfgeu r2,r20
do {
*cp++ = digits[(int)(num % 10)];
} while ((num /= 10) > 0);
if (negative)
*cp++ = '-';
*cp-- = 0;
10001c34: d8 12 18 00 l.sb 0(r18),r3
while (cp >= outbuf)
10001c38: 0c 00 00 07 l.bnf 10001c54 <serial_putnum+0xf0>
serial_putchar(*str++);
}
//-------------------------------------------------------------
// serial_putnum:
//-------------------------------------------------------------
void serial_putnum( int n )
10001c3c: 9d d4 ff ff l.addi r14,r20,-1
if (negative)
*cp++ = '-';
*cp-- = 0;
while (cp >= outbuf)
serial_putchar(*cp--);
10001c40: 90 62 00 00 l.lbs r3,0(r2)
10001c44: 9c 42 ff ff l.addi r2,r2,-1
10001c48: 07 ff ff 83 l.jal 10001a54 <serial_putchar>
} while ((num /= 10) > 0);
if (negative)
*cp++ = '-';
*cp-- = 0;
while (cp >= outbuf)
10001c4c: e4 02 70 00 l.sfeq r2,r14
10001c50: 0f ff ff fc l.bnf 10001c40 <serial_putnum+0xdc>
serial_putchar(*cp--);
}
10001c54: 9c 21 00 50 l.addi r1,r1,80
10001c58: 85 21 ff fc l.lwz r9,-4(r1)
10001c5c: 84 21 ff e4 l.lwz r1,-28(r1)
10001c60: 84 41 ff e8 l.lwz r2,-24(r1)
10001c64: 85 c1 ff ec l.lwz r14,-20(r1)
10001c68: 86 41 ff f0 l.lwz r18,-16(r1)
10001c6c: 86 81 ff f4 l.lwz r20,-12(r1)
10001c70: 86 c1 ff f8 l.lwz r22,-8(r1)
10001c74: 44 00 48 00 l.jr r9
unsigned long num;
 
/* Check if number is negative */
if (n < 0L) {
negative = 1;
num = -(n);
10001c78: e0 40 18 02 l.sub r2,r0,r3
const char digits[] = "0123456789ABCDEF";
unsigned long num;
 
/* Check if number is negative */
if (n < 0L) {
negative = 1;
10001c7c: 9e c0 00 01 l.addi r22,r0,1
10001c80: 03 ff ff d3 l.j 10001bcc <serial_putnum+0x68>
 
10001c84 <timer_init>:
 
//--------------------------------------------------------------------------
// timer_init:
//--------------------------------------------------------------------------
void timer_init(void)
{
10001c84: d7 e1 0f fc l.sw -4(r1),r1
10001c88: 9c 21 ff fc l.addi r1,r1,-4
 
}
10001c8c: 9c 21 00 04 l.addi r1,r1,4
10001c90: 84 21 ff fc l.lwz r1,-4(r1)
10001c94: 44 00 48 00 l.jr r9
 
10001c98 <timer_sleep>:
// Prototypes:
//-----------------------------------------------------------------
 
// General timer
void timer_init(void);
static t_time timer_now(void) { return TIMER_VAL; }
10001c98: 18 a0 12 00 l.movhi r5,0x1200
//--------------------------------------------------------------------------
// timer_sleep:
//--------------------------------------------------------------------------
void timer_sleep(int timeMs)
{
10001c9c: d7 e1 0f fc l.sw -4(r1),r1
10001ca0: a8 a5 01 00 l.ori r5,r5,0x100
10001ca4: 9c 21 ff fc l.addi r1,r1,-4
10001ca8: 84 c5 00 00 l.lwz r6,0(r5)
10001cac: 84 85 00 00 l.lwz r4,0(r5)
static long timer_diff(t_time a, t_time b) { return (long)(a - b); }
10001cb0: e0 84 30 02 l.sub r4,r4,r6
t_time t = timer_now();
 
while (timer_diff(timer_now(), t) < timeMs)
10001cb4: e5 a3 20 00 l.sfles r3,r4
10001cb8: 0f ff ff fd l.bnf 10001cac <timer_sleep+0x14>
;
}
10001cbc: 9c 21 00 04 l.addi r1,r1,4
10001cc0: 84 21 ff fc l.lwz r1,-4(r1)
10001cc4: 44 00 48 00 l.jr r9
 
10001cc8 <empty_syscall>:
volatile int syscall_done = 0;
 
//-----------------------------------------------------------------
// Syscall handling:
//-----------------------------------------------------------------
void empty_syscall(void) { syscall_done = 1; }
10001cc8: 18 60 10 00 l.movhi r3,0x1000
10001ccc: 9c 80 00 01 l.addi r4,r0,1
10001cd0: a8 63 2f f8 l.ori r3,r3,0x2ff8
10001cd4: d7 e1 0f fc l.sw -4(r1),r1
10001cd8: 9c 21 ff fc l.addi r1,r1,-4
10001cdc: d4 03 20 00 l.sw 0(r3),r4
10001ce0: 9c 21 00 04 l.addi r1,r1,4
10001ce4: 84 21 ff fc l.lwz r1,-4(r1)
10001ce8: 44 00 48 00 l.jr r9
 
10001cec <test>:
unsigned short sw;
unsigned short *psw;
unsigned char sb;
unsigned char *psb;
 
serial_putstr("\nTest:\n");
10001cec: 18 60 10 00 l.movhi r3,0x1000
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int test(void)
{
10001cf0: d7 e1 4f fc l.sw -4(r1),r9
10001cf4: d7 e1 17 f0 l.sw -16(r1),r2
10001cf8: d7 e1 0f ec l.sw -20(r1),r1
10001cfc: d7 e1 77 f4 l.sw -12(r1),r14
10001d00: d7 e1 97 f8 l.sw -8(r1),r18
unsigned short sw;
unsigned short *psw;
unsigned char sb;
unsigned char *psb;
 
serial_putstr("\nTest:\n");
10001d04: a8 63 2d 09 l.ori r3,r3,0x2d09
 
//-----------------------------------------------------------------
// main:
//-----------------------------------------------------------------
int test(void)
{
10001d08: 9c 21 ff e0 l.addi r1,r1,-32
 
// Assign empty syscall handler
exception_register_syscall_handler(empty_syscall);
 
serial_putstr("1. Initialised data\n");
assert(var == 0x1234); // .text
10001d0c: 18 40 10 00 l.movhi r2,0x1000
unsigned short sw;
unsigned short *psw;
unsigned char sb;
unsigned char *psb;
 
serial_putstr("\nTest:\n");
10001d10: 07 ff ff 83 l.jal 10001b1c <serial_putstr>
 
// Adjust ISR vector to match this app's vector offset
asm_set_isr_vector(asm_save_context);
 
// Assign empty syscall handler
exception_register_syscall_handler(empty_syscall);
10001d14: 18 60 10 00 l.movhi r3,0x1000
 
serial_putstr("1. Initialised data\n");
assert(var == 0x1234); // .text
10001d18: a8 42 2f d8 l.ori r2,r2,0x2fd8
 
// Adjust ISR vector to match this app's vector offset
asm_set_isr_vector(asm_save_context);
 
// Assign empty syscall handler
exception_register_syscall_handler(empty_syscall);
10001d1c: a8 63 1c c8 l.ori r3,r3,0x1cc8
10001d20: 07 ff fc e2 l.jal 100010a8 <exception_register_syscall_handler>
 
serial_putstr("1. Initialised data\n");
10001d24: 18 60 10 00 l.movhi r3,0x1000
10001d28: a8 63 2d 11 l.ori r3,r3,0x2d11
10001d2c: 07 ff ff 7c l.jal 10001b1c <serial_putstr>
assert(var == 0x1234); // .text
10001d30: 84 62 00 00 l.lwz r3,0(r2)
10001d34: bc 03 12 34 l.sfeqi r3,4660
10001d38: 10 00 00 0e l.bf 10001d70 <test+0x84>
10001d3c: 18 60 10 00 l.movhi r3,0x1000
10001d40: a8 63 2d 26 l.ori r3,r3,0x2d26
10001d44: d4 01 18 00 l.sw 0(r1),r3
10001d48: 18 60 10 00 l.movhi r3,0x1000
10001d4c: a8 63 2d 34 l.ori r3,r3,0x2d34
10001d50: d4 01 18 04 l.sw 4(r1),r3
10001d54: 9c 60 00 29 l.addi r3,r0,41
10001d58: d4 01 18 08 l.sw 8(r1),r3
10001d5c: 18 60 10 00 l.movhi r3,0x1000
10001d60: a8 63 2c 74 l.ori r3,r3,0x2c74
10001d64: 07 ff ff 20 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001d68: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001d6c: c8 00 00 00 lf.add.s r0,r0,r0
assert(uvar == 0x0); // .bss
10001d70: 19 c0 10 00 l.movhi r14,0x1000
10001d74: a9 ce 30 04 l.ori r14,r14,0x3004
10001d78: 84 6e 00 00 l.lwz r3,0(r14)
10001d7c: bc 03 00 00 l.sfeqi r3,0
10001d80: 0c 00 02 d1 l.bnf 100028c4 <test+0xbd8>
 
serial_putstr("2. Multiply\n");
10001d84: 18 60 10 00 l.movhi r3,0x1000
10001d88: a8 63 2d 47 l.ori r3,r3,0x2d47
10001d8c: 07 ff ff 64 l.jal 10001b1c <serial_putstr>
var = var * 3;
10001d90: 84 62 00 00 l.lwz r3,0(r2)
10001d94: e0 83 18 00 l.add r4,r3,r3
10001d98: e0 64 18 00 l.add r3,r4,r3
10001d9c: d4 02 18 00 l.sw 0(r2),r3
assert(var == 13980);
10001da0: 84 62 00 00 l.lwz r3,0(r2)
10001da4: bc 03 36 9c l.sfeqi r3,13980
10001da8: 10 00 00 0e l.bf 10001de0 <test+0xf4>
10001dac: 18 60 10 00 l.movhi r3,0x1000
10001db0: a8 63 2d 54 l.ori r3,r3,0x2d54
10001db4: d4 01 18 00 l.sw 0(r1),r3
10001db8: 18 60 10 00 l.movhi r3,0x1000
10001dbc: a8 63 2d 34 l.ori r3,r3,0x2d34
10001dc0: d4 01 18 04 l.sw 4(r1),r3
10001dc4: 9c 60 00 2e l.addi r3,r0,46
10001dc8: d4 01 18 08 l.sw 8(r1),r3
10001dcc: 18 60 10 00 l.movhi r3,0x1000
10001dd0: a8 63 2c 74 l.ori r3,r3,0x2c74
10001dd4: 07 ff ff 04 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001dd8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001ddc: c8 00 00 00 lf.add.s r0,r0,r0
var = -1;
10001de0: 9c 60 ff ff l.addi r3,r0,-1
10001de4: d4 02 18 00 l.sw 0(r2),r3
var = var * 3;
10001de8: 84 62 00 00 l.lwz r3,0(r2)
10001dec: e0 83 18 00 l.add r4,r3,r3
10001df0: e0 64 18 00 l.add r3,r4,r3
10001df4: d4 02 18 00 l.sw 0(r2),r3
assert(var == -3);
10001df8: 84 62 00 00 l.lwz r3,0(r2)
10001dfc: bc 03 ff fd l.sfeqi r3,-3
10001e00: 10 00 00 0e l.bf 10001e38 <test+0x14c>
10001e04: 18 60 10 00 l.movhi r3,0x1000
10001e08: a8 63 2d 61 l.ori r3,r3,0x2d61
10001e0c: d4 01 18 00 l.sw 0(r1),r3
10001e10: 18 60 10 00 l.movhi r3,0x1000
10001e14: a8 63 2d 34 l.ori r3,r3,0x2d34
10001e18: d4 01 18 04 l.sw 4(r1),r3
10001e1c: 9c 60 00 31 l.addi r3,r0,49
10001e20: d4 01 18 08 l.sw 8(r1),r3
10001e24: 18 60 10 00 l.movhi r3,0x1000
10001e28: a8 63 2c 74 l.ori r3,r3,0x2c74
10001e2c: 07 ff fe ee l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001e30: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001e34: c8 00 00 00 lf.add.s r0,r0,r0
var = -5;
10001e38: 9c 60 ff fb l.addi r3,r0,-5
10001e3c: d4 02 18 00 l.sw 0(r2),r3
var = var * 13;
10001e40: 84 62 00 00 l.lwz r3,0(r2)
10001e44: e0 83 18 00 l.add r4,r3,r3
10001e48: e0 84 18 00 l.add r4,r4,r3
10001e4c: b8 84 00 02 l.slli r4,r4,0x2
10001e50: e0 64 18 00 l.add r3,r4,r3
10001e54: d4 02 18 00 l.sw 0(r2),r3
assert(var == -65);
10001e58: 84 62 00 00 l.lwz r3,0(r2)
10001e5c: bc 03 ff bf l.sfeqi r3,-65
10001e60: 10 00 00 0e l.bf 10001e98 <test+0x1ac>
10001e64: 18 60 10 00 l.movhi r3,0x1000
10001e68: a8 63 2d 6b l.ori r3,r3,0x2d6b
10001e6c: d4 01 18 00 l.sw 0(r1),r3
10001e70: 18 60 10 00 l.movhi r3,0x1000
10001e74: a8 63 2d 34 l.ori r3,r3,0x2d34
10001e78: d4 01 18 04 l.sw 4(r1),r3
10001e7c: 9c 60 00 34 l.addi r3,r0,52
10001e80: d4 01 18 08 l.sw 8(r1),r3
10001e84: 18 60 10 00 l.movhi r3,0x1000
10001e88: a8 63 2c 74 l.ori r3,r3,0x2c74
10001e8c: 07 ff fe d6 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001e90: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001e94: c8 00 00 00 lf.add.s r0,r0,r0
var = -5;
10001e98: 9c 60 ff fb l.addi r3,r0,-5
var = var * -13;
10001e9c: 9c 80 ff f3 l.addi r4,r0,-13
var = var * 3;
assert(var == -3);
var = -5;
var = var * 13;
assert(var == -65);
var = -5;
10001ea0: d4 02 18 00 l.sw 0(r2),r3
var = var * -13;
10001ea4: 84 62 00 00 l.lwz r3,0(r2)
10001ea8: 04 00 03 04 l.jal 10002ab8 <__mulsi3>
10001eac: d4 02 58 00 l.sw 0(r2),r11
assert(var == (-5*-13));
10001eb0: 84 62 00 00 l.lwz r3,0(r2)
10001eb4: bc 03 00 41 l.sfeqi r3,65
10001eb8: 10 00 00 0e l.bf 10001ef0 <test+0x204>
10001ebc: 18 60 10 00 l.movhi r3,0x1000
10001ec0: a8 63 2d 76 l.ori r3,r3,0x2d76
10001ec4: d4 01 18 00 l.sw 0(r1),r3
10001ec8: 18 60 10 00 l.movhi r3,0x1000
10001ecc: a8 63 2d 34 l.ori r3,r3,0x2d34
10001ed0: d4 01 18 04 l.sw 4(r1),r3
10001ed4: 9c 60 00 37 l.addi r3,r0,55
10001ed8: d4 01 18 08 l.sw 8(r1),r3
10001edc: 18 60 10 00 l.movhi r3,0x1000
10001ee0: a8 63 2c 74 l.ori r3,r3,0x2c74
10001ee4: 07 ff fe c0 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001ee8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001eec: c8 00 00 00 lf.add.s r0,r0,r0
var = -123123415;
10001ef0: 18 60 f8 a9 l.movhi r3,0xf8a9
var = var * 9664563;
10001ef4: 18 80 00 93 l.movhi r4,0x93
var = var * 13;
assert(var == -65);
var = -5;
var = var * -13;
assert(var == (-5*-13));
var = -123123415;
10001ef8: a8 63 49 29 l.ori r3,r3,0x4929
var = var * 9664563;
10001efc: a8 84 78 33 l.ori r4,r4,0x7833
var = var * 13;
assert(var == -65);
var = -5;
var = var * -13;
assert(var == (-5*-13));
var = -123123415;
10001f00: d4 02 18 00 l.sw 0(r2),r3
var = var * 9664563;
10001f04: 84 62 00 00 l.lwz r3,0(r2)
10001f08: 04 00 02 ec l.jal 10002ab8 <__mulsi3>
assert(var == (-123123415*9664563));
10001f0c: 18 80 e6 8f l.movhi r4,0xe68f
assert(var == -65);
var = -5;
var = var * -13;
assert(var == (-5*-13));
var = -123123415;
var = var * 9664563;
10001f10: d4 02 58 00 l.sw 0(r2),r11
assert(var == (-123123415*9664563));
10001f14: a8 84 cb 2b l.ori r4,r4,0xcb2b
10001f18: 84 62 00 00 l.lwz r3,0(r2)
10001f1c: e4 03 20 00 l.sfeq r3,r4
10001f20: 10 00 00 0e l.bf 10001f58 <test+0x26c>
10001f24: 18 60 10 00 l.movhi r3,0x1000
10001f28: a8 63 2d 86 l.ori r3,r3,0x2d86
10001f2c: d4 01 18 00 l.sw 0(r1),r3
10001f30: 18 60 10 00 l.movhi r3,0x1000
10001f34: a8 63 2d 34 l.ori r3,r3,0x2d34
10001f38: d4 01 18 04 l.sw 4(r1),r3
10001f3c: 9c 60 00 3a l.addi r3,r0,58
10001f40: d4 01 18 08 l.sw 8(r1),r3
10001f44: 18 60 10 00 l.movhi r3,0x1000
10001f48: a8 63 2c 74 l.ori r3,r3,0x2c74
10001f4c: 07 ff fe a6 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001f50: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001f54: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("3. Divide\n");
10001f58: 18 60 10 00 l.movhi r3,0x1000
10001f5c: a8 63 2d a2 l.ori r3,r3,0x2da2
10001f60: 07 ff fe ef l.jal 10001b1c <serial_putstr>
var = 13980;
10001f64: 9c 60 36 9c l.addi r3,r0,13980
var = var / 5;
10001f68: 9c 80 00 05 l.addi r4,r0,5
var = -123123415;
var = var * 9664563;
assert(var == (-123123415*9664563));
 
serial_putstr("3. Divide\n");
var = 13980;
10001f6c: d4 02 18 00 l.sw 0(r2),r3
var = var / 5;
10001f70: 84 62 00 00 l.lwz r3,0(r2)
10001f74: 04 00 02 74 l.jal 10002944 <__divsi3>
10001f78: d4 02 58 00 l.sw 0(r2),r11
assert(var == 2796);
10001f7c: 84 62 00 00 l.lwz r3,0(r2)
10001f80: bc 03 0a ec l.sfeqi r3,2796
10001f84: 10 00 00 0e l.bf 10001fbc <test+0x2d0>
10001f88: 18 60 10 00 l.movhi r3,0x1000
10001f8c: a8 63 2d ad l.ori r3,r3,0x2dad
10001f90: d4 01 18 00 l.sw 0(r1),r3
10001f94: 18 60 10 00 l.movhi r3,0x1000
10001f98: a8 63 2d 34 l.ori r3,r3,0x2d34
10001f9c: d4 01 18 04 l.sw 4(r1),r3
10001fa0: 9c 60 00 3f l.addi r3,r0,63
10001fa4: d4 01 18 08 l.sw 8(r1),r3
10001fa8: 18 60 10 00 l.movhi r3,0x1000
10001fac: a8 63 2c 74 l.ori r3,r3,0x2c74
10001fb0: 07 ff fe 8d l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10001fb4: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10001fb8: c8 00 00 00 lf.add.s r0,r0,r0
var = var % 100;
10001fbc: 84 62 00 00 l.lwz r3,0(r2)
10001fc0: 9c 80 00 64 l.addi r4,r0,100
10001fc4: 04 00 02 7a l.jal 100029ac <__modsi3>
10001fc8: d4 02 58 00 l.sw 0(r2),r11
assert(var == 96);
10001fcc: 84 62 00 00 l.lwz r3,0(r2)
10001fd0: bc 03 00 60 l.sfeqi r3,96
10001fd4: 10 00 00 0e l.bf 1000200c <test+0x320>
10001fd8: 18 60 10 00 l.movhi r3,0x1000
10001fdc: a8 63 2d b9 l.ori r3,r3,0x2db9
10001fe0: d4 01 18 00 l.sw 0(r1),r3
10001fe4: 18 60 10 00 l.movhi r3,0x1000
10001fe8: a8 63 2d 34 l.ori r3,r3,0x2d34
10001fec: d4 01 18 04 l.sw 4(r1),r3
10001ff0: 9c 60 00 41 l.addi r3,r0,65
10001ff4: d4 01 18 08 l.sw 8(r1),r3
10001ff8: 18 60 10 00 l.movhi r3,0x1000
10001ffc: a8 63 2c 74 l.ori r3,r3,0x2c74
10002000: 07 ff fe 79 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002004: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002008: c8 00 00 00 lf.add.s r0,r0,r0
var = -1273;
1000200c: 9c 60 fb 07 l.addi r3,r0,-1273
var = var / 19;
10002010: 9c 80 00 13 l.addi r4,r0,19
var = 13980;
var = var / 5;
assert(var == 2796);
var = var % 100;
assert(var == 96);
var = -1273;
10002014: d4 02 18 00 l.sw 0(r2),r3
var = var / 19;
10002018: 84 62 00 00 l.lwz r3,0(r2)
1000201c: 04 00 02 4a l.jal 10002944 <__divsi3>
10002020: d4 02 58 00 l.sw 0(r2),r11
assert(var == -67);
10002024: 84 62 00 00 l.lwz r3,0(r2)
10002028: bc 03 ff bd l.sfeqi r3,-67
1000202c: 10 00 00 0e l.bf 10002064 <test+0x378>
10002030: 18 60 10 00 l.movhi r3,0x1000
10002034: a8 63 2d c3 l.ori r3,r3,0x2dc3
10002038: d4 01 18 00 l.sw 0(r1),r3
1000203c: 18 60 10 00 l.movhi r3,0x1000
10002040: a8 63 2d 34 l.ori r3,r3,0x2d34
10002044: d4 01 18 04 l.sw 4(r1),r3
10002048: 9c 60 00 44 l.addi r3,r0,68
1000204c: d4 01 18 08 l.sw 8(r1),r3
10002050: 18 60 10 00 l.movhi r3,0x1000
10002054: a8 63 2c 74 l.ori r3,r3,0x2c74
10002058: 07 ff fe 63 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
1000205c: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002060: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("4. Shift left\n");
10002064: 18 60 10 00 l.movhi r3,0x1000
var = 0x1;
10002068: 9e 40 00 01 l.addi r18,r0,1
assert(var == 96);
var = -1273;
var = var / 19;
assert(var == -67);
 
serial_putstr("4. Shift left\n");
1000206c: a8 63 2d ce l.ori r3,r3,0x2dce
10002070: 07 ff fe ab l.jal 10001b1c <serial_putstr>
var = 0x1;
10002074: d4 02 90 00 l.sw 0(r2),r18
var <<= 31;
assert(var == 0x80000000);
10002078: 18 80 80 00 l.movhi r4,0x8000
var = var / 19;
assert(var == -67);
 
serial_putstr("4. Shift left\n");
var = 0x1;
var <<= 31;
1000207c: 84 62 00 00 l.lwz r3,0(r2)
10002080: b8 63 00 1f l.slli r3,r3,0x1f
10002084: d4 02 18 00 l.sw 0(r2),r3
assert(var == 0x80000000);
10002088: 84 62 00 00 l.lwz r3,0(r2)
1000208c: e4 03 20 00 l.sfeq r3,r4
10002090: 10 00 00 0e l.bf 100020c8 <test+0x3dc>
10002094: 18 60 10 00 l.movhi r3,0x1000
10002098: a8 63 2d dd l.ori r3,r3,0x2ddd
1000209c: d4 01 18 00 l.sw 0(r1),r3
100020a0: 18 60 10 00 l.movhi r3,0x1000
100020a4: a8 63 2d 34 l.ori r3,r3,0x2d34
100020a8: d4 01 18 04 l.sw 4(r1),r3
100020ac: 9c 60 00 49 l.addi r3,r0,73
100020b0: d4 01 18 08 l.sw 8(r1),r3
100020b4: 18 60 10 00 l.movhi r3,0x1000
100020b8: a8 63 2c 74 l.ori r3,r3,0x2c74
100020bc: 07 ff fe 4a l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100020c0: a8 32 00 00 l.ori r1,r18,0x0
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100020c4: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("5. Shift right\n");
100020c8: 18 60 10 00 l.movhi r3,0x1000
100020cc: a8 63 2d ef l.ori r3,r3,0x2def
100020d0: 07 ff fe 93 l.jal 10001b1c <serial_putstr>
uvar = 0x80000000;
100020d4: 18 60 80 00 l.movhi r3,0x8000
uvar >>= 1;
assert(uvar == 0x40000000);
100020d8: 18 80 40 00 l.movhi r4,0x4000
var = 0x1;
var <<= 31;
assert(var == 0x80000000);
 
serial_putstr("5. Shift right\n");
uvar = 0x80000000;
100020dc: d4 0e 18 00 l.sw 0(r14),r3
uvar >>= 1;
100020e0: 84 6e 00 00 l.lwz r3,0(r14)
100020e4: b8 63 00 41 l.srli r3,r3,0x1
100020e8: d4 0e 18 00 l.sw 0(r14),r3
assert(uvar == 0x40000000);
100020ec: 84 6e 00 00 l.lwz r3,0(r14)
100020f0: e4 03 20 00 l.sfeq r3,r4
100020f4: 10 00 00 0e l.bf 1000212c <test+0x440>
100020f8: 18 60 10 00 l.movhi r3,0x1000
100020fc: a8 63 2d ff l.ori r3,r3,0x2dff
10002100: d4 01 18 00 l.sw 0(r1),r3
10002104: 18 60 10 00 l.movhi r3,0x1000
10002108: a8 63 2d 34 l.ori r3,r3,0x2d34
1000210c: d4 01 18 04 l.sw 4(r1),r3
10002110: 9c 60 00 4e l.addi r3,r0,78
10002114: d4 01 18 08 l.sw 8(r1),r3
10002118: 18 60 10 00 l.movhi r3,0x1000
1000211c: a8 63 2c 74 l.ori r3,r3,0x2c74
10002120: 07 ff fe 31 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002124: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002128: c8 00 00 00 lf.add.s r0,r0,r0
uvar >>= 30;
1000212c: 84 6e 00 00 l.lwz r3,0(r14)
10002130: b8 63 00 5e l.srli r3,r3,0x1e
10002134: d4 0e 18 00 l.sw 0(r14),r3
assert(uvar == 0x00000001);
10002138: 84 6e 00 00 l.lwz r3,0(r14)
1000213c: bc 03 00 01 l.sfeqi r3,1
10002140: 10 00 00 0e l.bf 10002178 <test+0x48c>
10002144: 18 60 10 00 l.movhi r3,0x1000
10002148: a8 63 2e 12 l.ori r3,r3,0x2e12
1000214c: d4 01 18 00 l.sw 0(r1),r3
10002150: 18 60 10 00 l.movhi r3,0x1000
10002154: a8 63 2d 34 l.ori r3,r3,0x2d34
10002158: d4 01 18 04 l.sw 4(r1),r3
1000215c: 9c 60 00 50 l.addi r3,r0,80
10002160: d4 01 18 08 l.sw 8(r1),r3
10002164: 18 60 10 00 l.movhi r3,0x1000
10002168: a8 63 2c 74 l.ori r3,r3,0x2c74
1000216c: 07 ff fe 1e l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002170: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002174: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("6. Shift right arithmetic\n");
10002178: 18 60 10 00 l.movhi r3,0x1000
1000217c: a8 63 2e 25 l.ori r3,r3,0x2e25
10002180: 07 ff fe 67 l.jal 10001b1c <serial_putstr>
var = 0x80000000;
10002184: 18 60 80 00 l.movhi r3,0x8000
var >>= 1;
assert(var == 0xC0000000);
10002188: 18 80 c0 00 l.movhi r4,0xc000
assert(uvar == 0x40000000);
uvar >>= 30;
assert(uvar == 0x00000001);
 
serial_putstr("6. Shift right arithmetic\n");
var = 0x80000000;
1000218c: d4 02 18 00 l.sw 0(r2),r3
var >>= 1;
10002190: 84 62 00 00 l.lwz r3,0(r2)
10002194: b8 63 00 81 l.srai r3,r3,0x1
10002198: d4 02 18 00 l.sw 0(r2),r3
assert(var == 0xC0000000);
1000219c: 84 62 00 00 l.lwz r3,0(r2)
100021a0: e4 03 20 00 l.sfeq r3,r4
100021a4: 10 00 00 0e l.bf 100021dc <test+0x4f0>
100021a8: 18 60 10 00 l.movhi r3,0x1000
100021ac: a8 63 2e 40 l.ori r3,r3,0x2e40
100021b0: d4 01 18 00 l.sw 0(r1),r3
100021b4: 18 60 10 00 l.movhi r3,0x1000
100021b8: a8 63 2d 34 l.ori r3,r3,0x2d34
100021bc: d4 01 18 04 l.sw 4(r1),r3
100021c0: 9c 60 00 55 l.addi r3,r0,85
100021c4: d4 01 18 08 l.sw 8(r1),r3
100021c8: 18 60 10 00 l.movhi r3,0x1000
100021cc: a8 63 2c 74 l.ori r3,r3,0x2c74
100021d0: 07 ff fe 05 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100021d4: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100021d8: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("7. Signed comparision\n");
100021dc: 18 60 10 00 l.movhi r3,0x1000
100021e0: a8 63 2e 52 l.ori r3,r3,0x2e52
100021e4: 07 ff fe 4e l.jal 10001b1c <serial_putstr>
var = -1;
100021e8: 9c 60 ff ff l.addi r3,r0,-1
100021ec: d4 02 18 00 l.sw 0(r2),r3
assert(var < 1);
100021f0: 84 62 00 00 l.lwz r3,0(r2)
100021f4: bd a3 00 00 l.sflesi r3,0
100021f8: 10 00 00 0e l.bf 10002230 <test+0x544>
100021fc: 18 60 10 00 l.movhi r3,0x1000
10002200: a8 63 2e 69 l.ori r3,r3,0x2e69
10002204: d4 01 18 00 l.sw 0(r1),r3
10002208: 18 60 10 00 l.movhi r3,0x1000
1000220c: a8 63 2d 34 l.ori r3,r3,0x2d34
10002210: d4 01 18 04 l.sw 4(r1),r3
10002214: 9c 60 00 59 l.addi r3,r0,89
10002218: d4 01 18 08 l.sw 8(r1),r3
1000221c: 18 60 10 00 l.movhi r3,0x1000
10002220: a8 63 2c 74 l.ori r3,r3,0x2c74
10002224: 07 ff fd f0 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002228: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000222c: c8 00 00 00 lf.add.s r0,r0,r0
x = 10;
assert(var < x);
10002230: 84 62 00 00 l.lwz r3,0(r2)
10002234: bd a3 00 09 l.sflesi r3,9
10002238: 0c 00 01 95 l.bnf 1000288c <test+0xba0>
assert(!(var > x));
1000223c: 84 62 00 00 l.lwz r3,0(r2)
10002240: bd a3 00 0a l.sflesi r3,10
10002244: 0c 00 01 84 l.bnf 10002854 <test+0xb68>
x = -3;
assert(var > x);
10002248: 84 62 00 00 l.lwz r3,0(r2)
1000224c: bd 63 ff fe l.sfgesi r3,-2
10002250: 0c 00 01 73 l.bnf 1000281c <test+0xb30>
assert(x <= var);
10002254: 84 42 00 00 l.lwz r2,0(r2)
10002258: bd 62 ff fd l.sfgesi r2,-3
1000225c: 0c 00 01 62 l.bnf 100027e4 <test+0xaf8>
 
serial_putstr("8. Word access\n");
10002260: 18 60 10 00 l.movhi r3,0x1000
uvar = 0x12345678;
10002264: 18 40 12 34 l.movhi r2,0x1234
assert(!(var > x));
x = -3;
assert(var > x);
assert(x <= var);
 
serial_putstr("8. Word access\n");
10002268: a8 63 2e 95 l.ori r3,r3,0x2e95
uvar = 0x12345678;
1000226c: a8 42 56 78 l.ori r2,r2,0x5678
assert(!(var > x));
x = -3;
assert(var > x);
assert(x <= var);
 
serial_putstr("8. Word access\n");
10002270: 07 ff fe 2b l.jal 10001b1c <serial_putstr>
uvar = 0x12345678;
assert(uvar == 0x12345678);
10002274: 18 60 12 34 l.movhi r3,0x1234
x = -3;
assert(var > x);
assert(x <= var);
 
serial_putstr("8. Word access\n");
uvar = 0x12345678;
10002278: d4 0e 10 00 l.sw 0(r14),r2
assert(uvar == 0x12345678);
1000227c: a8 63 56 78 l.ori r3,r3,0x5678
10002280: 84 4e 00 00 l.lwz r2,0(r14)
10002284: e4 02 18 00 l.sfeq r2,r3
10002288: 10 00 00 0e l.bf 100022c0 <test+0x5d4>
1000228c: 18 40 10 00 l.movhi r2,0x1000
10002290: 18 60 10 00 l.movhi r3,0x1000
10002294: a8 42 2e a5 l.ori r2,r2,0x2ea5
10002298: a8 63 2c 74 l.ori r3,r3,0x2c74
1000229c: d4 01 10 00 l.sw 0(r1),r2
100022a0: 18 40 10 00 l.movhi r2,0x1000
100022a4: a8 42 2d 34 l.ori r2,r2,0x2d34
100022a8: d4 01 10 04 l.sw 4(r1),r2
100022ac: 9c 40 00 63 l.addi r2,r0,99
100022b0: d4 01 10 08 l.sw 8(r1),r2
100022b4: 07 ff fd cc l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100022b8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100022bc: c8 00 00 00 lf.add.s r0,r0,r0
sw = uvar;
100022c0: 84 4e 00 00 l.lwz r2,0(r14)
assert(sw == 0x5678);
100022c4: a4 42 ff ff l.andi r2,r2,0xffff
100022c8: bc 02 56 78 l.sfeqi r2,22136
100022cc: 10 00 00 0e l.bf 10002304 <test+0x618>
100022d0: 18 40 10 00 l.movhi r2,0x1000
100022d4: 18 60 10 00 l.movhi r3,0x1000
100022d8: a8 42 2e b8 l.ori r2,r2,0x2eb8
100022dc: a8 63 2c 74 l.ori r3,r3,0x2c74
100022e0: d4 01 10 00 l.sw 0(r1),r2
100022e4: 18 40 10 00 l.movhi r2,0x1000
100022e8: a8 42 2d 34 l.ori r2,r2,0x2d34
100022ec: d4 01 10 04 l.sw 4(r1),r2
100022f0: 9c 40 00 65 l.addi r2,r0,101
100022f4: d4 01 10 08 l.sw 8(r1),r2
100022f8: 07 ff fd bb l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100022fc: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002300: c8 00 00 00 lf.add.s r0,r0,r0
psw = &uvar;
assert(*psw++ == 0x1234);
10002304: 94 4e 00 00 l.lhz r2,0(r14)
10002308: bc 02 12 34 l.sfeqi r2,4660
1000230c: 10 00 00 0e l.bf 10002344 <test+0x658>
10002310: 18 40 10 00 l.movhi r2,0x1000
10002314: 18 60 10 00 l.movhi r3,0x1000
10002318: a8 42 2e c5 l.ori r2,r2,0x2ec5
1000231c: a8 63 2c 74 l.ori r3,r3,0x2c74
10002320: d4 01 10 00 l.sw 0(r1),r2
10002324: 18 40 10 00 l.movhi r2,0x1000
10002328: a8 42 2d 34 l.ori r2,r2,0x2d34
1000232c: d4 01 10 04 l.sw 4(r1),r2
10002330: 9c 40 00 67 l.addi r2,r0,103
10002334: d4 01 10 08 l.sw 8(r1),r2
10002338: 07 ff fd ab l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
1000233c: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002340: c8 00 00 00 lf.add.s r0,r0,r0
assert(*psw++ == 0x5678);
10002344: 94 4e 00 02 l.lhz r2,2(r14)
10002348: bc 02 56 78 l.sfeqi r2,22136
1000234c: 10 00 01 1f l.bf 100027c8 <test+0xadc>
10002350: 9c 60 00 68 l.addi r3,r0,104
10002354: 1a 40 10 00 l.movhi r18,0x1000
10002358: 18 40 10 00 l.movhi r2,0x1000
1000235c: d4 01 18 08 l.sw 8(r1),r3
10002360: aa 52 2e d6 l.ori r18,r18,0x2ed6
10002364: a8 42 2d 34 l.ori r2,r2,0x2d34
10002368: 18 60 10 00 l.movhi r3,0x1000
1000236c: d4 01 90 00 l.sw 0(r1),r18
10002370: d4 01 10 04 l.sw 4(r1),r2
10002374: a8 63 2c 74 l.ori r3,r3,0x2c74
10002378: 07 ff fd 9b l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
1000237c: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002380: c8 00 00 00 lf.add.s r0,r0,r0
10002384: 94 6e 00 02 l.lhz r3,2(r14)
psw = &uvar;
*psw = 0xcafe;
10002388: 9c 80 ca fe l.addi r4,r0,-13570
assert(*psw++ == 0xcafe);
assert(*psw++ == 0x5678);
1000238c: bc 03 56 78 l.sfeqi r3,22136
assert(sw == 0x5678);
psw = &uvar;
assert(*psw++ == 0x1234);
assert(*psw++ == 0x5678);
psw = &uvar;
*psw = 0xcafe;
10002390: dc 0e 20 00 l.sh 0(r14),r4
assert(*psw++ == 0xcafe);
assert(*psw++ == 0x5678);
10002394: 10 00 01 11 l.bf 100027d8 <test+0xaec>
10002398: 9c 60 00 6c l.addi r3,r0,108
1000239c: d4 01 90 00 l.sw 0(r1),r18
100023a0: d4 01 18 08 l.sw 8(r1),r3
100023a4: 18 60 10 00 l.movhi r3,0x1000
100023a8: d4 01 10 04 l.sw 4(r1),r2
100023ac: a8 63 2c 74 l.ori r3,r3,0x2c74
100023b0: 07 ff fd 8d l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100023b4: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100023b8: c8 00 00 00 lf.add.s r0,r0,r0
psw = &uvar;
*(++psw) = 0xbabe;
100023bc: 9c 80 ba be l.addi r4,r0,-17730
100023c0: 94 6e 00 00 l.lhz r3,0(r14)
100023c4: dc 0e 20 02 l.sh 2(r14),r4
psw = &uvar;
assert(*psw++ == 0xcafe);
100023c8: a8 80 ca fe l.ori r4,r0,0xcafe
100023cc: e4 23 20 00 l.sfne r3,r4
100023d0: 0c 00 00 1b l.bnf 1000243c <test+0x750>
100023d4: 18 60 10 00 l.movhi r3,0x1000
100023d8: d4 01 10 04 l.sw 4(r1),r2
100023dc: a8 63 2e e7 l.ori r3,r3,0x2ee7
100023e0: d4 01 18 00 l.sw 0(r1),r3
100023e4: 9c 60 00 70 l.addi r3,r0,112
100023e8: d4 01 18 08 l.sw 8(r1),r3
100023ec: 18 60 10 00 l.movhi r3,0x1000
100023f0: a8 63 2c 74 l.ori r3,r3,0x2c74
100023f4: 07 ff fd 7c l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100023f8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100023fc: c8 00 00 00 lf.add.s r0,r0,r0
assert(*psw++ == 0xbabe);
10002400: a8 80 ba be l.ori r4,r0,0xbabe
10002404: 94 6e 00 02 l.lhz r3,2(r14)
10002408: e4 03 20 00 l.sfeq r3,r4
1000240c: 10 00 00 0c l.bf 1000243c <test+0x750>
10002410: 18 60 10 00 l.movhi r3,0x1000
10002414: d4 01 10 04 l.sw 4(r1),r2
10002418: a8 63 2e f8 l.ori r3,r3,0x2ef8
1000241c: 9c 40 00 71 l.addi r2,r0,113
10002420: d4 01 18 00 l.sw 0(r1),r3
10002424: 18 60 10 00 l.movhi r3,0x1000
10002428: d4 01 10 08 l.sw 8(r1),r2
1000242c: a8 63 2c 74 l.ori r3,r3,0x2c74
10002430: 07 ff fd 6d l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002434: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002438: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("9. Byte access\n");
1000243c: 18 60 10 00 l.movhi r3,0x1000
uvar = 0x12345678;
10002440: 18 40 12 34 l.movhi r2,0x1234
*(++psw) = 0xbabe;
psw = &uvar;
assert(*psw++ == 0xcafe);
assert(*psw++ == 0xbabe);
 
serial_putstr("9. Byte access\n");
10002444: a8 63 2f 09 l.ori r3,r3,0x2f09
uvar = 0x12345678;
10002448: a8 42 56 78 l.ori r2,r2,0x5678
*(++psw) = 0xbabe;
psw = &uvar;
assert(*psw++ == 0xcafe);
assert(*psw++ == 0xbabe);
 
serial_putstr("9. Byte access\n");
1000244c: 07 ff fd b4 l.jal 10001b1c <serial_putstr>
uvar = 0x12345678;
assert(uvar == 0x12345678);
10002450: 18 60 12 34 l.movhi r3,0x1234
psw = &uvar;
assert(*psw++ == 0xcafe);
assert(*psw++ == 0xbabe);
 
serial_putstr("9. Byte access\n");
uvar = 0x12345678;
10002454: d4 0e 10 00 l.sw 0(r14),r2
assert(uvar == 0x12345678);
10002458: a8 63 56 78 l.ori r3,r3,0x5678
1000245c: 84 4e 00 00 l.lwz r2,0(r14)
10002460: e4 02 18 00 l.sfeq r2,r3
10002464: 10 00 00 0e l.bf 1000249c <test+0x7b0>
10002468: 18 40 10 00 l.movhi r2,0x1000
1000246c: 18 60 10 00 l.movhi r3,0x1000
10002470: a8 42 2e a5 l.ori r2,r2,0x2ea5
10002474: a8 63 2c 74 l.ori r3,r3,0x2c74
10002478: d4 01 10 00 l.sw 0(r1),r2
1000247c: 18 40 10 00 l.movhi r2,0x1000
10002480: a8 42 2d 34 l.ori r2,r2,0x2d34
10002484: d4 01 10 04 l.sw 4(r1),r2
10002488: 9c 40 00 75 l.addi r2,r0,117
1000248c: d4 01 10 08 l.sw 8(r1),r2
10002490: 07 ff fd 55 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002494: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002498: c8 00 00 00 lf.add.s r0,r0,r0
sb = uvar;
1000249c: 84 4e 00 00 l.lwz r2,0(r14)
assert(sb == 0x78);
100024a0: a4 42 00 ff l.andi r2,r2,0xff
100024a4: bc 02 00 78 l.sfeqi r2,120
100024a8: 10 00 00 0e l.bf 100024e0 <test+0x7f4>
100024ac: 18 40 10 00 l.movhi r2,0x1000
100024b0: 18 60 10 00 l.movhi r3,0x1000
100024b4: a8 42 2f 19 l.ori r2,r2,0x2f19
100024b8: a8 63 2c 74 l.ori r3,r3,0x2c74
100024bc: d4 01 10 00 l.sw 0(r1),r2
100024c0: 18 40 10 00 l.movhi r2,0x1000
100024c4: a8 42 2d 34 l.ori r2,r2,0x2d34
100024c8: d4 01 10 04 l.sw 4(r1),r2
100024cc: 9c 40 00 77 l.addi r2,r0,119
100024d0: d4 01 10 08 l.sw 8(r1),r2
100024d4: 07 ff fd 44 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100024d8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100024dc: c8 00 00 00 lf.add.s r0,r0,r0
psb = &uvar;
assert(*psb++ == 0x12);
100024e0: 8c 4e 00 00 l.lbz r2,0(r14)
100024e4: bc 02 00 12 l.sfeqi r2,18
100024e8: 10 00 00 0e l.bf 10002520 <test+0x834>
100024ec: 18 40 10 00 l.movhi r2,0x1000
100024f0: 18 60 10 00 l.movhi r3,0x1000
100024f4: a8 42 2f 24 l.ori r2,r2,0x2f24
100024f8: a8 63 2c 74 l.ori r3,r3,0x2c74
100024fc: d4 01 10 00 l.sw 0(r1),r2
10002500: 18 40 10 00 l.movhi r2,0x1000
10002504: a8 42 2d 34 l.ori r2,r2,0x2d34
10002508: d4 01 10 04 l.sw 4(r1),r2
1000250c: 9c 40 00 79 l.addi r2,r0,121
10002510: d4 01 10 08 l.sw 8(r1),r2
10002514: 07 ff fd 34 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002518: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000251c: c8 00 00 00 lf.add.s r0,r0,r0
assert(*psb++ == 0x34);
10002520: 8c 4e 00 01 l.lbz r2,1(r14)
10002524: bc 02 00 34 l.sfeqi r2,52
10002528: 10 00 00 0e l.bf 10002560 <test+0x874>
1000252c: 18 40 10 00 l.movhi r2,0x1000
10002530: 18 60 10 00 l.movhi r3,0x1000
10002534: a8 42 2f 33 l.ori r2,r2,0x2f33
10002538: a8 63 2c 74 l.ori r3,r3,0x2c74
1000253c: d4 01 10 00 l.sw 0(r1),r2
10002540: 18 40 10 00 l.movhi r2,0x1000
10002544: a8 42 2d 34 l.ori r2,r2,0x2d34
10002548: d4 01 10 04 l.sw 4(r1),r2
1000254c: 9c 40 00 7a l.addi r2,r0,122
10002550: d4 01 10 08 l.sw 8(r1),r2
10002554: 07 ff fd 24 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002558: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000255c: c8 00 00 00 lf.add.s r0,r0,r0
assert(*psb++ == 0x56);
10002560: 8c 4e 00 02 l.lbz r2,2(r14)
10002564: bc 02 00 56 l.sfeqi r2,86
10002568: 10 00 00 0e l.bf 100025a0 <test+0x8b4>
1000256c: 18 40 10 00 l.movhi r2,0x1000
10002570: 18 60 10 00 l.movhi r3,0x1000
10002574: a8 42 2f 42 l.ori r2,r2,0x2f42
10002578: a8 63 2c 74 l.ori r3,r3,0x2c74
1000257c: d4 01 10 00 l.sw 0(r1),r2
10002580: 18 40 10 00 l.movhi r2,0x1000
10002584: a8 42 2d 34 l.ori r2,r2,0x2d34
10002588: d4 01 10 04 l.sw 4(r1),r2
1000258c: 9c 40 00 7b l.addi r2,r0,123
10002590: d4 01 10 08 l.sw 8(r1),r2
10002594: 07 ff fd 14 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002598: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000259c: c8 00 00 00 lf.add.s r0,r0,r0
assert(*psb++ == 0x78);
100025a0: 8c 4e 00 03 l.lbz r2,3(r14)
100025a4: bc 02 00 78 l.sfeqi r2,120
100025a8: 10 00 00 0e l.bf 100025e0 <test+0x8f4>
100025ac: 18 40 10 00 l.movhi r2,0x1000
100025b0: 18 60 10 00 l.movhi r3,0x1000
100025b4: a8 42 2f 51 l.ori r2,r2,0x2f51
100025b8: a8 63 2c 74 l.ori r3,r3,0x2c74
100025bc: d4 01 10 00 l.sw 0(r1),r2
100025c0: 18 40 10 00 l.movhi r2,0x1000
100025c4: a8 42 2d 34 l.ori r2,r2,0x2d34
100025c8: d4 01 10 04 l.sw 4(r1),r2
100025cc: 9c 40 00 7c l.addi r2,r0,124
100025d0: d4 01 10 08 l.sw 8(r1),r2
100025d4: 07 ff fd 04 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100025d8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100025dc: c8 00 00 00 lf.add.s r0,r0,r0
psb = &uvar;
*psb++ = 0xab;
100025e0: 9c 80 ff ab l.addi r4,r0,-85
assert(uvar == 0xab345678);
100025e4: 18 60 ab 34 l.movhi r3,0xab34
assert(*psb++ == 0x12);
assert(*psb++ == 0x34);
assert(*psb++ == 0x56);
assert(*psb++ == 0x78);
psb = &uvar;
*psb++ = 0xab;
100025e8: d8 0e 20 00 l.sb 0(r14),r4
assert(uvar == 0xab345678);
100025ec: a8 63 56 78 l.ori r3,r3,0x5678
100025f0: 84 4e 00 00 l.lwz r2,0(r14)
100025f4: e4 02 18 00 l.sfeq r2,r3
100025f8: 10 00 00 0e l.bf 10002630 <test+0x944>
100025fc: 18 40 10 00 l.movhi r2,0x1000
10002600: 18 60 10 00 l.movhi r3,0x1000
10002604: a8 42 2f 60 l.ori r2,r2,0x2f60
10002608: a8 63 2c 74 l.ori r3,r3,0x2c74
1000260c: d4 01 10 00 l.sw 0(r1),r2
10002610: 18 40 10 00 l.movhi r2,0x1000
10002614: a8 42 2d 34 l.ori r2,r2,0x2d34
10002618: d4 01 10 04 l.sw 4(r1),r2
1000261c: 9c 40 00 7f l.addi r2,r0,127
10002620: d4 01 10 08 l.sw 8(r1),r2
10002624: 07 ff fc f0 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002628: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000262c: c8 00 00 00 lf.add.s r0,r0,r0
*psb++ = 0xcd;
10002630: 9c 80 ff cd l.addi r4,r0,-51
assert(uvar == 0xabcd5678);
10002634: 18 60 ab cd l.movhi r3,0xabcd
assert(*psb++ == 0x56);
assert(*psb++ == 0x78);
psb = &uvar;
*psb++ = 0xab;
assert(uvar == 0xab345678);
*psb++ = 0xcd;
10002638: d8 0e 20 01 l.sb 1(r14),r4
assert(uvar == 0xabcd5678);
1000263c: a8 63 56 78 l.ori r3,r3,0x5678
10002640: 84 4e 00 00 l.lwz r2,0(r14)
10002644: e4 02 18 00 l.sfeq r2,r3
10002648: 10 00 00 0e l.bf 10002680 <test+0x994>
1000264c: 18 40 10 00 l.movhi r2,0x1000
10002650: 18 60 10 00 l.movhi r3,0x1000
10002654: a8 42 2f 73 l.ori r2,r2,0x2f73
10002658: a8 63 2c 74 l.ori r3,r3,0x2c74
1000265c: d4 01 10 00 l.sw 0(r1),r2
10002660: 18 40 10 00 l.movhi r2,0x1000
10002664: a8 42 2d 34 l.ori r2,r2,0x2d34
10002668: d4 01 10 04 l.sw 4(r1),r2
1000266c: 9c 40 00 81 l.addi r2,r0,129
10002670: d4 01 10 08 l.sw 8(r1),r2
10002674: 07 ff fc dc l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002678: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000267c: c8 00 00 00 lf.add.s r0,r0,r0
*psb++ = 0xef;
10002680: 9c 80 ff ef l.addi r4,r0,-17
assert(uvar == 0xabcdef78);
10002684: 18 60 ab cd l.movhi r3,0xabcd
psb = &uvar;
*psb++ = 0xab;
assert(uvar == 0xab345678);
*psb++ = 0xcd;
assert(uvar == 0xabcd5678);
*psb++ = 0xef;
10002688: d8 0e 20 02 l.sb 2(r14),r4
assert(uvar == 0xabcdef78);
1000268c: a8 63 ef 78 l.ori r3,r3,0xef78
10002690: 84 4e 00 00 l.lwz r2,0(r14)
10002694: e4 02 18 00 l.sfeq r2,r3
10002698: 10 00 00 0e l.bf 100026d0 <test+0x9e4>
1000269c: 18 40 10 00 l.movhi r2,0x1000
100026a0: 18 60 10 00 l.movhi r3,0x1000
100026a4: a8 42 2f 86 l.ori r2,r2,0x2f86
100026a8: a8 63 2c 74 l.ori r3,r3,0x2c74
100026ac: d4 01 10 00 l.sw 0(r1),r2
100026b0: 18 40 10 00 l.movhi r2,0x1000
100026b4: a8 42 2d 34 l.ori r2,r2,0x2d34
100026b8: d4 01 10 04 l.sw 4(r1),r2
100026bc: 9c 40 00 83 l.addi r2,r0,131
100026c0: d4 01 10 08 l.sw 8(r1),r2
100026c4: 07 ff fc c8 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100026c8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100026cc: c8 00 00 00 lf.add.s r0,r0,r0
*psb++ = 0x01;
100026d0: 9c 80 00 01 l.addi r4,r0,1
assert(uvar == 0xabcdef01);
100026d4: 18 60 ab cd l.movhi r3,0xabcd
assert(uvar == 0xab345678);
*psb++ = 0xcd;
assert(uvar == 0xabcd5678);
*psb++ = 0xef;
assert(uvar == 0xabcdef78);
*psb++ = 0x01;
100026d8: d8 0e 20 03 l.sb 3(r14),r4
assert(uvar == 0xabcdef01);
100026dc: a8 63 ef 01 l.ori r3,r3,0xef01
100026e0: 84 4e 00 00 l.lwz r2,0(r14)
100026e4: e4 02 18 00 l.sfeq r2,r3
100026e8: 10 00 00 0e l.bf 10002720 <test+0xa34>
100026ec: 18 40 10 00 l.movhi r2,0x1000
100026f0: 18 60 10 00 l.movhi r3,0x1000
100026f4: a8 42 2f 99 l.ori r2,r2,0x2f99
100026f8: a8 63 2c 74 l.ori r3,r3,0x2c74
100026fc: d4 01 10 00 l.sw 0(r1),r2
10002700: 18 40 10 00 l.movhi r2,0x1000
10002704: a8 42 2d 34 l.ori r2,r2,0x2d34
10002708: d4 01 10 04 l.sw 4(r1),r2
1000270c: 9c 40 00 85 l.addi r2,r0,133
10002710: d4 01 10 08 l.sw 8(r1),r2
10002714: 07 ff fc b4 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002718: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000271c: c8 00 00 00 lf.add.s r0,r0,r0
 
serial_putstr("10. Comparision\n");
10002720: 18 60 10 00 l.movhi r3,0x1000
longvar = 0x1db9;
10002724: 18 40 10 00 l.movhi r2,0x1000
*psb++ = 0xef;
assert(uvar == 0xabcdef78);
*psb++ = 0x01;
assert(uvar == 0xabcdef01);
 
serial_putstr("10. Comparision\n");
10002728: a8 63 2f ac l.ori r3,r3,0x2fac
longvar = 0x1db9;
1000272c: a8 42 30 00 l.ori r2,r2,0x3000
*psb++ = 0xef;
assert(uvar == 0xabcdef78);
*psb++ = 0x01;
assert(uvar == 0xabcdef01);
 
serial_putstr("10. Comparision\n");
10002730: 07 ff fc fb l.jal 10001b1c <serial_putstr>
longvar = 0x1db9;
10002734: 9c 60 1d b9 l.addi r3,r0,7609
if (longvar >= 0xFFF8 && longvar <= 0xFFFF)
10002738: a8 80 ff f7 l.ori r4,r0,0xfff7
assert(uvar == 0xabcdef78);
*psb++ = 0x01;
assert(uvar == 0xabcdef01);
 
serial_putstr("10. Comparision\n");
longvar = 0x1db9;
1000273c: d4 02 18 00 l.sw 0(r2),r3
if (longvar >= 0xFFF8 && longvar <= 0xFFFF)
10002740: 84 62 00 00 l.lwz r3,0(r2)
10002744: e4 a3 20 00 l.sfleu r3,r4
10002748: 10 00 00 05 l.bf 1000275c <test+0xa70>
1000274c: a8 60 ff ff l.ori r3,r0,0xffff
10002750: 84 42 00 00 l.lwz r2,0(r2)
10002754: e4 42 18 00 l.sfgtu r2,r3
10002758: 0c 00 00 0b l.bnf 10002784 <test+0xa98>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
1000275c: 9c 20 00 00 l.addi r1,r0,0
 
// No error?
if (exit_code == 0)
{
// Trap instruction
__asm__ __volatile__ ( "\t l.trap 0 ");
10002760: 21 00 00 00 l.trap 0x0
assert(0);
}
 
// Success
exit(0);
}
10002764: 9c 21 00 20 l.addi r1,r1,32
10002768: 9d 60 00 00 l.addi r11,r0,0
1000276c: 85 21 ff fc l.lwz r9,-4(r1)
10002770: 84 21 ff ec l.lwz r1,-20(r1)
10002774: 84 41 ff f0 l.lwz r2,-16(r1)
10002778: 85 c1 ff f4 l.lwz r14,-12(r1)
1000277c: 86 41 ff f8 l.lwz r18,-8(r1)
10002780: 44 00 48 00 l.jr r9
 
serial_putstr("10. Comparision\n");
longvar = 0x1db9;
if (longvar >= 0xFFF8 && longvar <= 0xFFFF)
{
serial_putstr("- Incorrect comparision\n");
10002784: 18 60 10 00 l.movhi r3,0x1000
assert(0);
10002788: 18 40 10 00 l.movhi r2,0x1000
 
serial_putstr("10. Comparision\n");
longvar = 0x1db9;
if (longvar >= 0xFFF8 && longvar <= 0xFFFF)
{
serial_putstr("- Incorrect comparision\n");
1000278c: a8 63 2f bd l.ori r3,r3,0x2fbd
assert(0);
10002790: a8 42 2d 07 l.ori r2,r2,0x2d07
 
serial_putstr("10. Comparision\n");
longvar = 0x1db9;
if (longvar >= 0xFFF8 && longvar <= 0xFFFF)
{
serial_putstr("- Incorrect comparision\n");
10002794: 07 ff fc e2 l.jal 10001b1c <serial_putstr>
assert(0);
10002798: d4 01 10 00 l.sw 0(r1),r2
1000279c: 18 40 10 00 l.movhi r2,0x1000
100027a0: 18 60 10 00 l.movhi r3,0x1000
100027a4: a8 42 2d 34 l.ori r2,r2,0x2d34
100027a8: a8 63 2c 74 l.ori r3,r3,0x2c74
100027ac: d4 01 10 04 l.sw 4(r1),r2
100027b0: 9c 40 00 8c l.addi r2,r0,140
100027b4: d4 01 10 08 l.sw 8(r1),r2
100027b8: 07 ff fc 8b l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100027bc: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100027c0: c8 00 00 00 lf.add.s r0,r0,r0
100027c4: 03 ff ff e6 l.j 1000275c <test+0xa70>
assert(sw == 0x5678);
psw = &uvar;
assert(*psw++ == 0x1234);
assert(*psw++ == 0x5678);
psw = &uvar;
*psw = 0xcafe;
100027c8: 18 40 10 00 l.movhi r2,0x1000
100027cc: 9c 80 ca fe l.addi r4,r0,-13570
100027d0: a8 42 30 04 l.ori r2,r2,0x3004
100027d4: dc 02 20 00 l.sh 0(r2),r4
assert(*psw++ == 0xcafe);
assert(*psw++ == 0x5678);
psw = &uvar;
*(++psw) = 0xbabe;
100027d8: 9c 40 ba be l.addi r2,r0,-17730
100027dc: dc 0e 10 02 l.sh 2(r14),r2
100027e0: 03 ff ff 17 l.j 1000243c <test+0x750>
x = 10;
assert(var < x);
assert(!(var > x));
x = -3;
assert(var > x);
assert(x <= var);
100027e4: 18 40 10 00 l.movhi r2,0x1000
100027e8: 18 60 10 00 l.movhi r3,0x1000
100027ec: a8 42 2e 8c l.ori r2,r2,0x2e8c
100027f0: a8 63 2c 74 l.ori r3,r3,0x2c74
100027f4: d4 01 10 00 l.sw 0(r1),r2
100027f8: 18 40 10 00 l.movhi r2,0x1000
100027fc: a8 42 2d 34 l.ori r2,r2,0x2d34
10002800: d4 01 10 04 l.sw 4(r1),r2
10002804: 9c 40 00 5f l.addi r2,r0,95
10002808: d4 01 10 08 l.sw 8(r1),r2
1000280c: 07 ff fc 76 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002810: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002814: c8 00 00 00 lf.add.s r0,r0,r0
10002818: 03 ff fe 92 l.j 10002260 <test+0x574>
assert(var < 1);
x = 10;
assert(var < x);
assert(!(var > x));
x = -3;
assert(var > x);
1000281c: 18 60 10 00 l.movhi r3,0x1000
10002820: a8 63 2e 84 l.ori r3,r3,0x2e84
10002824: d4 01 18 00 l.sw 0(r1),r3
10002828: 18 60 10 00 l.movhi r3,0x1000
1000282c: a8 63 2d 34 l.ori r3,r3,0x2d34
10002830: d4 01 18 04 l.sw 4(r1),r3
10002834: 9c 60 00 5e l.addi r3,r0,94
10002838: d4 01 18 08 l.sw 8(r1),r3
1000283c: 18 60 10 00 l.movhi r3,0x1000
10002840: a8 63 2c 74 l.ori r3,r3,0x2c74
10002844: 07 ff fc 68 l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002848: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
1000284c: c8 00 00 00 lf.add.s r0,r0,r0
10002850: 03 ff fe 81 l.j 10002254 <test+0x568>
serial_putstr("7. Signed comparision\n");
var = -1;
assert(var < 1);
x = 10;
assert(var < x);
assert(!(var > x));
10002854: 18 60 10 00 l.movhi r3,0x1000
10002858: a8 63 2e 79 l.ori r3,r3,0x2e79
1000285c: d4 01 18 00 l.sw 0(r1),r3
10002860: 18 60 10 00 l.movhi r3,0x1000
10002864: a8 63 2d 34 l.ori r3,r3,0x2d34
10002868: d4 01 18 04 l.sw 4(r1),r3
1000286c: 9c 60 00 5c l.addi r3,r0,92
10002870: d4 01 18 08 l.sw 8(r1),r3
10002874: 18 60 10 00 l.movhi r3,0x1000
10002878: a8 63 2c 74 l.ori r3,r3,0x2c74
1000287c: 07 ff fc 5a l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
10002880: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
10002884: c8 00 00 00 lf.add.s r0,r0,r0
10002888: 03 ff fe 70 l.j 10002248 <test+0x55c>
 
serial_putstr("7. Signed comparision\n");
var = -1;
assert(var < 1);
x = 10;
assert(var < x);
1000288c: 18 60 10 00 l.movhi r3,0x1000
10002890: a8 63 2e 71 l.ori r3,r3,0x2e71
10002894: d4 01 18 00 l.sw 0(r1),r3
10002898: 18 60 10 00 l.movhi r3,0x1000
1000289c: a8 63 2d 34 l.ori r3,r3,0x2d34
100028a0: d4 01 18 04 l.sw 4(r1),r3
100028a4: 9c 60 00 5b l.addi r3,r0,91
100028a8: d4 01 18 08 l.sw 8(r1),r3
100028ac: 18 60 10 00 l.movhi r3,0x1000
100028b0: a8 63 2c 74 l.ori r3,r3,0x2c74
100028b4: 07 ff fc 4c l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100028b8: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100028bc: c8 00 00 00 lf.add.s r0,r0,r0
100028c0: 03 ff fe 5f l.j 1000223c <test+0x550>
// Assign empty syscall handler
exception_register_syscall_handler(empty_syscall);
 
serial_putstr("1. Initialised data\n");
assert(var == 0x1234); // .text
assert(uvar == 0x0); // .bss
100028c4: 18 60 10 00 l.movhi r3,0x1000
100028c8: a8 63 2d 3b l.ori r3,r3,0x2d3b
100028cc: d4 01 18 00 l.sw 0(r1),r3
100028d0: 18 60 10 00 l.movhi r3,0x1000
100028d4: a8 63 2d 34 l.ori r3,r3,0x2d34
100028d8: d4 01 18 04 l.sw 4(r1),r3
100028dc: 9c 60 00 2a l.addi r3,r0,42
100028e0: d4 01 18 08 l.sw 8(r1),r3
100028e4: 18 60 10 00 l.movhi r3,0x1000
100028e8: a8 63 2c 74 l.ori r3,r3,0x2c74
100028ec: 07 ff fc 3e l.jal 100019e4 <printf>
}
 
static inline void exit(unsigned exit_code)
{
volatile register char t1 asm ("r1") = exit_code;
100028f0: 9c 20 00 01 l.addi r1,r0,1
__asm__ __volatile__ ( "\t l.trap 0 ");
}
else
{
// Invalid instruction!
__asm__ __volatile__ ( "\t lf.add.s r0,r0,r0 ");
100028f4: c8 00 00 00 lf.add.s r0,r0,r0
100028f8: 03 ff fd 23 l.j 10001d84 <test+0x98>
 
100028fc <__udivsi3>:
 
long udivmodsi4 ();
 
long
__udivsi3 (long a, long b)
{
100028fc: d7 e1 4f fc l.sw -4(r1),r9
10002900: d7 e1 0f f8 l.sw -8(r1),r1
return udivmodsi4 (a, b, 0);
10002904: 9c a0 00 00 l.addi r5,r0,0
 
long udivmodsi4 ();
 
long
__udivsi3 (long a, long b)
{
10002908: 9c 21 ff f8 l.addi r1,r1,-8
return udivmodsi4 (a, b, 0);
1000290c: 04 00 00 40 l.jal 10002a0c <udivmodsi4>
}
10002910: 9c 21 00 08 l.addi r1,r1,8
10002914: 85 21 ff fc l.lwz r9,-4(r1)
10002918: 84 21 ff f8 l.lwz r1,-8(r1)
1000291c: 44 00 48 00 l.jr r9
 
10002920 <__umodsi3>:
 
long
__umodsi3 (long a, long b)
{
10002920: d7 e1 4f fc l.sw -4(r1),r9
10002924: d7 e1 0f f8 l.sw -8(r1),r1
return udivmodsi4 (a, b, 1);
10002928: 9c a0 00 01 l.addi r5,r0,1
return udivmodsi4 (a, b, 0);
}
 
long
__umodsi3 (long a, long b)
{
1000292c: 9c 21 ff f8 l.addi r1,r1,-8
return udivmodsi4 (a, b, 1);
10002930: 04 00 00 37 l.jal 10002a0c <udivmodsi4>
}
10002934: 9c 21 00 08 l.addi r1,r1,8
10002938: 85 21 ff fc l.lwz r9,-4(r1)
1000293c: 84 21 ff f8 l.lwz r1,-8(r1)
10002940: 44 00 48 00 l.jr r9
 
10002944 <__divsi3>:
 
long udivmodsi4 ();
 
long
__divsi3 (long a, long b)
{
10002944: d7 e1 17 f8 l.sw -8(r1),r2
10002948: d7 e1 4f fc l.sw -4(r1),r9
1000294c: d7 e1 0f f4 l.sw -12(r1),r1
int neg = 0;
long res;
 
if (a < 0)
10002950: bd 63 00 00 l.sfgesi r3,0
 
long udivmodsi4 ();
 
long
__divsi3 (long a, long b)
{
10002954: 9c 21 ff f4 l.addi r1,r1,-12
int neg = 0;
10002958: 9c 40 00 00 l.addi r2,r0,0
long res;
 
if (a < 0)
1000295c: 0c 00 00 0d l.bnf 10002990 <__divsi3+0x4c>
{
a = -a;
neg = !neg;
}
 
if (b < 0)
10002960: bd 64 00 00 l.sfgesi r4,0
10002964: 0c 00 00 0f l.bnf 100029a0 <__divsi3+0x5c>
{
b = -b;
neg = !neg;
}
 
res = udivmodsi4 (a, b, 0);
10002968: 9c a0 00 00 l.addi r5,r0,0
1000296c: 04 00 00 28 l.jal 10002a0c <udivmodsi4>
 
if (neg)
10002970: bc 02 00 00 l.sfeqi r2,0
10002974: 10 00 00 02 l.bf 1000297c <__divsi3+0x38>
res = -res;
10002978: e1 60 58 02 l.sub r11,r0,r11
 
return res;
}
1000297c: 9c 21 00 0c l.addi r1,r1,12
10002980: 85 21 ff fc l.lwz r9,-4(r1)
10002984: 84 21 ff f4 l.lwz r1,-12(r1)
10002988: 84 41 ff f8 l.lwz r2,-8(r1)
1000298c: 44 00 48 00 l.jr r9
{
a = -a;
neg = !neg;
}
 
if (b < 0)
10002990: bd 64 00 00 l.sfgesi r4,0
int neg = 0;
long res;
 
if (a < 0)
{
a = -a;
10002994: e0 60 18 02 l.sub r3,r0,r3
neg = !neg;
10002998: 9c 40 00 01 l.addi r2,r0,1
}
 
if (b < 0)
1000299c: 13 ff ff f3 l.bf 10002968 <__divsi3+0x24>
{
b = -b;
100029a0: e0 80 20 02 l.sub r4,r0,r4
100029a4: ac 42 00 01 l.xori r2,r2,1
100029a8: 03 ff ff f0 l.j 10002968 <__divsi3+0x24>
 
100029ac <__modsi3>:
return res;
}
 
long
__modsi3 (long a, long b)
{
100029ac: d7 e1 4f fc l.sw -4(r1),r9
100029b0: d7 e1 0f f8 l.sw -8(r1),r1
int neg = 0;
long res;
 
if (a < 0)
100029b4: bd 63 00 00 l.sfgesi r3,0
return res;
}
 
long
__modsi3 (long a, long b)
{
100029b8: 9c 21 ff f8 l.addi r1,r1,-8
100029bc: b8 c4 00 9f l.srai r6,r4,0x1f
int neg = 0;
long res;
 
if (a < 0)
100029c0: 0c 00 00 09 l.bnf 100029e4 <__modsi3+0x38>
100029c4: e0 86 20 05 l.xor r4,r6,r4
}
 
if (b < 0)
b = -b;
 
res = udivmodsi4 (a, b, 1);
100029c8: 9c a0 00 01 l.addi r5,r0,1
100029cc: e0 84 30 02 l.sub r4,r4,r6
100029d0: 04 00 00 0f l.jal 10002a0c <udivmodsi4>
 
if (neg)
res = -res;
 
return res;
}
100029d4: 9c 21 00 08 l.addi r1,r1,8
100029d8: 85 21 ff fc l.lwz r9,-4(r1)
100029dc: 84 21 ff f8 l.lwz r1,-8(r1)
100029e0: 44 00 48 00 l.jr r9
100029e4: e0 86 20 05 l.xor r4,r6,r4
}
 
if (b < 0)
b = -b;
 
res = udivmodsi4 (a, b, 1);
100029e8: e0 60 18 02 l.sub r3,r0,r3
100029ec: 9c a0 00 01 l.addi r5,r0,1
100029f0: e0 84 30 02 l.sub r4,r4,r6
100029f4: 04 00 00 06 l.jal 10002a0c <udivmodsi4>
 
if (neg)
res = -res;
 
return res;
}
100029f8: 9c 21 00 08 l.addi r1,r1,8
b = -b;
 
res = udivmodsi4 (a, b, 1);
 
if (neg)
res = -res;
100029fc: e1 60 58 02 l.sub r11,r0,r11
 
return res;
}
10002a00: 85 21 ff fc l.lwz r9,-4(r1)
10002a04: 84 21 ff f8 l.lwz r1,-8(r1)
10002a08: 44 00 48 00 l.jr r9
 
10002a0c <udivmodsi4>:
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
 
unsigned long
udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
10002a0c: d7 e1 0f fc l.sw -4(r1),r1
unsigned long bit = 1;
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
10002a10: e4 64 18 00 l.sfgeu r4,r3
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
 
unsigned long
udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
10002a14: 9c 21 ff fc l.addi r1,r1,-4
unsigned long bit = 1;
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
10002a18: 10 00 00 26 l.bf 10002ab0 <udivmodsi4+0xa4>
10002a1c: bd 64 00 00 l.sfgesi r4,0
<http://www.gnu.org/licenses/>. */
 
unsigned long
udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
unsigned long bit = 1;
10002a20: 9c c0 00 01 l.addi r6,r0,1
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
10002a24: 10 00 00 06 l.bf 10002a3c <udivmodsi4+0x30>
10002a28: 00 00 00 13 l.j 10002a74 <udivmodsi4+0x68>
10002a2c: bd 88 00 00 l.sfltsi r8,0
10002a30: 0c 00 00 0e l.bnf 10002a68 <udivmodsi4+0x5c>
10002a34: bd 84 00 00 l.sfltsi r4,0
10002a38: 10 00 00 0f l.bf 10002a74 <udivmodsi4+0x68>
{
den <<=1;
bit <<=1;
10002a3c: e0 c6 30 00 l.add r6,r6,r6
unsigned long bit = 1;
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
{
den <<=1;
10002a40: e0 84 20 00 l.add r4,r4,r4
udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
unsigned long bit = 1;
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
10002a44: e1 00 30 02 l.sub r8,r0,r6
10002a48: e4 43 20 00 l.sfgtu r3,r4
10002a4c: 9c e0 00 01 l.addi r7,r0,1
10002a50: e1 08 30 04 l.or r8,r8,r6
10002a54: 10 00 00 02 l.bf 10002a5c <udivmodsi4+0x50>
10002a58: 9c e0 00 00 l.addi r7,r0,0
10002a5c: a4 e7 00 ff l.andi r7,r7,0xff
10002a60: bc 07 00 00 l.sfeqi r7,0
10002a64: 0f ff ff f2 l.bnf 10002a2c <udivmodsi4+0x20>
{
den <<=1;
bit <<=1;
}
while (bit)
10002a68: bc 26 00 00 l.sfnei r6,0
10002a6c: a9 66 00 00 l.ori r11,r6,0x0
10002a70: 0c 00 00 0a l.bnf 10002a98 <udivmodsi4+0x8c>
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
{
den <<=1;
bit <<=1;
10002a74: 9d 60 00 00 l.addi r11,r0,0
}
while (bit)
{
if (num >= den)
10002a78: e4 83 20 00 l.sfltu r3,r4
10002a7c: 10 00 00 03 l.bf 10002a88 <udivmodsi4+0x7c>
{
num -= den;
10002a80: e0 63 20 02 l.sub r3,r3,r4
res |= bit;
10002a84: e1 6b 30 04 l.or r11,r11,r6
}
bit >>=1;
10002a88: b8 c6 00 41 l.srli r6,r6,0x1
den >>=1;
10002a8c: b8 84 00 41 l.srli r4,r4,0x1
while (den < num && bit && !(den & (1L<<31)))
{
den <<=1;
bit <<=1;
}
while (bit)
10002a90: bc 06 00 00 l.sfeqi r6,0
10002a94: 0f ff ff f9 l.bnf 10002a78 <udivmodsi4+0x6c>
res |= bit;
}
bit >>=1;
den >>=1;
}
if (modwanted) return num;
10002a98: bc 05 00 00 l.sfeqi r5,0
10002a9c: 10 00 00 02 l.bf 10002aa4 <udivmodsi4+0x98>
10002aa0: a9 63 00 00 l.ori r11,r3,0x0
return res;
}
10002aa4: 9c 21 00 04 l.addi r1,r1,4
10002aa8: 84 21 ff fc l.lwz r1,-4(r1)
10002aac: 44 00 48 00 l.jr r9
udivmodsi4(unsigned long num, unsigned long den, int modwanted)
{
unsigned long bit = 1;
unsigned long res = 0;
 
while (den < num && bit && !(den & (1L<<31)))
10002ab0: 9c c0 00 01 l.addi r6,r0,1
10002ab4: 03 ff ff f0 l.j 10002a74 <udivmodsi4+0x68>
 
10002ab8 <__mulsi3>:
 
typedef unsigned int USItype __attribute__ ((mode (SI)));
 
USItype
__mulsi3 (USItype a, USItype b)
{
10002ab8: d7 e1 0f fc l.sw -4(r1),r1
USItype c = 0;
 
while (a != 0)
10002abc: bc 03 00 00 l.sfeqi r3,0
 
typedef unsigned int USItype __attribute__ ((mode (SI)));
 
USItype
__mulsi3 (USItype a, USItype b)
{
10002ac0: 9c 21 ff fc l.addi r1,r1,-4
USItype c = 0;
 
while (a != 0)
10002ac4: 10 00 00 0d l.bf 10002af8 <__mulsi3+0x40>
typedef unsigned int USItype __attribute__ ((mode (SI)));
 
USItype
__mulsi3 (USItype a, USItype b)
{
USItype c = 0;
10002ac8: 9d 60 00 00 l.addi r11,r0,0
 
while (a != 0)
{
if (a & 1)
10002acc: a4 a3 00 01 l.andi r5,r3,0x1
10002ad0: b8 63 00 41 l.srli r3,r3,0x1
10002ad4: bc 05 00 00 l.sfeqi r5,0
10002ad8: 10 00 00 02 l.bf 10002ae0 <__mulsi3+0x28>
c += b;
10002adc: e1 6b 20 00 l.add r11,r11,r4
USItype
__mulsi3 (USItype a, USItype b)
{
USItype c = 0;
 
while (a != 0)
10002ae0: bc 03 00 00 l.sfeqi r3,0
{
if (a & 1)
c += b;
a >>= 1;
b <<= 1;
10002ae4: e0 84 20 00 l.add r4,r4,r4
USItype
__mulsi3 (USItype a, USItype b)
{
USItype c = 0;
 
while (a != 0)
10002ae8: 0f ff ff f9 l.bnf 10002acc <__mulsi3+0x14>
a >>= 1;
b <<= 1;
}
 
return c;
}
10002aec: 9c 21 00 04 l.addi r1,r1,4
10002af0: 84 21 ff fc l.lwz r1,-4(r1)
10002af4: 44 00 48 00 l.jr r9
typedef unsigned int USItype __attribute__ ((mode (SI)));
 
USItype
__mulsi3 (USItype a, USItype b)
{
USItype c = 0;
10002af8: a9 63 00 00 l.ori r11,r3,0x0
10002afc: 03 ff ff fc l.j 10002aec <__mulsi3+0x34>
10002b00: 10 00 12 b8 l.bf 100075e0 <_end+0x35d0>
10002b04: 10 00 11 a0 l.bf 10007184 <_end+0x3174>
10002b08: 10 00 11 bc l.bf 100071f8 <_end+0x31e8>
10002b0c: 10 00 11 f0 l.bf 100072cc <_end+0x32bc>
10002b10: 10 00 12 24 l.bf 100073a0 <_end+0x3390>
10002b14: 10 00 12 58 l.bf 10007474 <_end+0x3464>
10002b18: 10 00 12 78 l.bf 100074f8 <_end+0x34e8>
10002b1c: 10 00 12 98 l.bf 1000757c <_end+0x356c>
10002b20: 10 00 11 10 l.bf 10006f60 <_end+0x2f50>
10002b24: 10 00 18 dc l.bf 10008e94 <_end+0x4e84>
10002b28: 10 00 16 2c l.bf 100083d8 <_end+0x43c8>
10002b2c: 10 00 16 2c l.bf 100083dc <_end+0x43cc>
10002b30: 10 00 16 2c l.bf 100083e0 <_end+0x43d0>
10002b34: 10 00 16 2c l.bf 100083e4 <_end+0x43d4>
10002b38: 10 00 16 2c l.bf 100083e8 <_end+0x43d8>
10002b3c: 10 00 16 2c l.bf 100083ec <_end+0x43dc>
10002b40: 10 00 16 2c l.bf 100083f0 <_end+0x43e0>
10002b44: 10 00 18 c4 l.bf 10008e54 <_end+0x4e44>
10002b48: 10 00 18 ac l.bf 10008df8 <_end+0x4de8>
10002b4c: 10 00 16 2c l.bf 100083fc <_end+0x43ec>
10002b50: 10 00 16 2c l.bf 10008400 <_end+0x43f0>
10002b54: 10 00 16 2c l.bf 10008404 <_end+0x43f4>
10002b58: 10 00 16 2c l.bf 10008408 <_end+0x43f8>
10002b5c: 10 00 16 2c l.bf 1000840c <_end+0x43fc>
10002b60: 10 00 16 2c l.bf 10008410 <_end+0x4400>
10002b64: 10 00 16 2c l.bf 10008414 <_end+0x4404>
10002b68: 10 00 16 2c l.bf 10008418 <_end+0x4408>
10002b6c: 10 00 16 2c l.bf 1000841c <_end+0x440c>
10002b70: 10 00 16 2c l.bf 10008420 <_end+0x4410>
10002b74: 10 00 16 2c l.bf 10008424 <_end+0x4414>
10002b78: 10 00 16 2c l.bf 10008428 <_end+0x4418>
10002b7c: 10 00 16 2c l.bf 1000842c <_end+0x441c>
10002b80: 10 00 16 2c l.bf 10008430 <_end+0x4420>
10002b84: 10 00 16 2c l.bf 10008434 <_end+0x4424>
10002b88: 10 00 16 2c l.bf 10008438 <_end+0x4428>
10002b8c: 10 00 16 2c l.bf 1000843c <_end+0x442c>
10002b90: 10 00 16 2c l.bf 10008440 <_end+0x4430>
10002b94: 10 00 16 2c l.bf 10008444 <_end+0x4434>
10002b98: 10 00 16 2c l.bf 10008448 <_end+0x4438>
10002b9c: 10 00 16 2c l.bf 1000844c <_end+0x443c>
10002ba0: 10 00 16 2c l.bf 10008450 <_end+0x4440>
10002ba4: 10 00 16 2c l.bf 10008454 <_end+0x4444>
10002ba8: 10 00 16 2c l.bf 10008458 <_end+0x4448>
10002bac: 10 00 16 2c l.bf 1000845c <_end+0x444c>
10002bb0: 10 00 16 2c l.bf 10008460 <_end+0x4450>
10002bb4: 10 00 16 2c l.bf 10008464 <_end+0x4454>
10002bb8: 10 00 16 2c l.bf 10008468 <_end+0x4458>
10002bbc: 10 00 16 2c l.bf 1000846c <_end+0x445c>
10002bc0: 10 00 16 2c l.bf 10008470 <_end+0x4460>
10002bc4: 10 00 16 2c l.bf 10008474 <_end+0x4464>
10002bc8: 10 00 16 2c l.bf 10008478 <_end+0x4468>
10002bcc: 10 00 16 2c l.bf 1000847c <_end+0x446c>
10002bd0: 10 00 16 2c l.bf 10008480 <_end+0x4470>
10002bd4: 10 00 16 2c l.bf 10008484 <_end+0x4474>
10002bd8: 10 00 16 2c l.bf 10008488 <_end+0x4478>
10002bdc: 10 00 16 2c l.bf 1000848c <_end+0x447c>
10002be0: 10 00 16 2c l.bf 10008490 <_end+0x4480>
10002be4: 10 00 16 2c l.bf 10008494 <_end+0x4484>
10002be8: 10 00 16 2c l.bf 10008498 <_end+0x4488>
10002bec: 10 00 16 2c l.bf 1000849c <_end+0x448c>
10002bf0: 10 00 16 2c l.bf 100084a0 <_end+0x4490>
10002bf4: 10 00 16 2c l.bf 100084a4 <_end+0x4494>
10002bf8: 10 00 16 2c l.bf 100084a8 <_end+0x4498>
10002bfc: 10 00 16 2c l.bf 100084ac <_end+0x449c>
10002c00: 10 00 18 7c l.bf 10008df0 <_end+0x4de0>
10002c04: 10 00 16 2c l.bf 100084b4 <_end+0x44a4>
10002c08: 10 00 16 2c l.bf 100084b8 <_end+0x44a8>
10002c0c: 10 00 16 2c l.bf 100084bc <_end+0x44ac>
10002c10: 10 00 16 2c l.bf 100084c0 <_end+0x44b0>
10002c14: 10 00 16 2c l.bf 100084c4 <_end+0x44b4>
10002c18: 10 00 16 2c l.bf 100084c8 <_end+0x44b8>
10002c1c: 10 00 18 68 l.bf 10008dbc <_end+0x4dac>
10002c20: 10 00 18 50 l.bf 10008d60 <_end+0x4d50>
10002c24: 10 00 16 2c l.bf 100084d4 <_end+0x44c4>
10002c28: 10 00 16 2c l.bf 100084d8 <_end+0x44c8>
10002c2c: 10 00 16 2c l.bf 100084dc <_end+0x44cc>
10002c30: 10 00 16 2c l.bf 100084e0 <_end+0x44d0>
10002c34: 10 00 16 2c l.bf 100084e4 <_end+0x44d4>
10002c38: 10 00 16 2c l.bf 100084e8 <_end+0x44d8>
10002c3c: 10 00 16 2c l.bf 100084ec <_end+0x44dc>
10002c40: 10 00 18 3c l.bf 10008d30 <_end+0x4d20>
10002c44: 10 00 16 2c l.bf 100084f4 <_end+0x44e4>
10002c48: 10 00 16 2c l.bf 100084f8 <_end+0x44e8>
10002c4c: 10 00 16 2c l.bf 100084fc <_end+0x44ec>
10002c50: 10 00 18 1c l.bf 10008cc0 <_end+0x4cb0>
10002c54: 10 00 16 2c l.bf 10008504 <_end+0x44f4>
10002c58: 10 00 16 2c l.bf 10008508 <_end+0x44f8>
10002c5c: 10 00 17 34 l.bf 1000892c <_end+0x491c>
10002c60: 10 00 16 2c l.bf 10008510 <_end+0x4500>
10002c64: 10 00 16 2c l.bf 10008514 <_end+0x4504>
10002c68: 10 00 16 2c l.bf 10008518 <_end+0x4508>
10002c6c: 10 00 16 2c l.bf 1000851c <_end+0x450c>
10002c70: 10 00 18 1c l.bf 10008ce0 <_end+0x4cd0>
10002c74: 41 73 73 65 *unknown*
10002c78: 72 74 20 66 *unknown*
10002c7c: 61 69 6c 65 *unknown*
10002c80: 64 3a 20 25 *unknown*
10002c84: 73 20 28 25 *unknown*
10002c88: 73 3a 25 64 *unknown*
10002c8c: 29 0a 00 22 *unknown*
10002c90: 53 59 53 43 *unknown*
10002c94: 41 4c 4c 21 *unknown*
10002c98: 22 00 2e 2e *unknown*
10002c9c: 2f 63 6f 6d *unknown*
10002ca0: 6d 6f 6e 2f *unknown*
10002ca4: 65 78 63 65 *unknown*
10002ca8: 70 74 69 6f *unknown*
10002cac: 6e 2e 63 00 *unknown*
10002cb0: 22 42 52 45 *unknown*
10002cb4: 41 4b 21 22 *unknown*
10002cb8: 00 22 45 58 l.j 10894218 <_end+0x890208>
10002cbc: 54 5f 49 4e *unknown*
10002cc0: 54 21 22 00 *unknown*
10002cc4: 22 46 41 55 *unknown*
10002cc8: 4c 54 22 00 *unknown*
10002ccc: 22 4d 55 4c *unknown*
10002cd0: 54 21 22 00 *unknown*
10002cd4: 22 55 4d 55 *unknown*
10002cd8: 4c 54 21 22 *unknown*
10002cdc: 00 22 44 49 l.j 10893e00 <_end+0x88fdf0>
10002ce0: 56 21 22 00 *unknown*
10002ce4: 22 55 44 49 *unknown*
10002ce8: 56 21 22 00 *unknown*
10002cec: 22 55 4e 4b *unknown*
10002cf0: 4e 4f 57 4e *unknown*
10002cf4: 22 00 72 65 *unknown*
10002cf8: 63 75 72 73 *unknown*
10002cfc: 69 76 65 5f *unknown*
10002d00: 69 6e 74 20 *unknown*
10002d04: 3d 3d 20 30 *unknown*
10002d08: 00 0a 54 65 l.j 10297e9c <_end+0x293e8c>
10002d0c: 73 74 3a 0a *unknown*
10002d10: 00 31 2e 20 l.j 10c4e590 <_end+0xc4a580>
10002d14: 49 6e 69 74 *unknown*
10002d18: 69 61 6c 69 *unknown*
10002d1c: 73 65 64 20 *unknown*
10002d20: 64 61 74 61 *unknown*
10002d24: 0a 00 76 61 *unknown*
10002d28: 72 20 3d 3d *unknown*
10002d2c: 20 30 78 31 *unknown*
10002d30: 32 33 34 00 *unknown*
10002d34: 74 65 73 74 *unknown*
10002d38: 2e 63 00 75 *unknown*
10002d3c: 76 61 72 20 *unknown*
10002d40: 3d 3d 20 30 *unknown*
10002d44: 78 30 00 32 *unknown*
10002d48: 2e 20 4d 75 *unknown*
10002d4c: 6c 74 69 70 *unknown*
10002d50: 6c 79 0a 00 *unknown*
10002d54: 76 61 72 20 *unknown*
10002d58: 3d 3d 20 31 *unknown*
10002d5c: 33 39 38 30 *unknown*
10002d60: 00 76 61 72 l.j 11d9b328 <_end+0x1d97318>
10002d64: 20 3d 3d 20 *unknown*
10002d68: 2d 33 00 76 *unknown*
10002d6c: 61 72 20 3d *unknown*
10002d70: 3d 20 2d 36 *unknown*
10002d74: 35 00 76 61 *unknown*
10002d78: 72 20 3d 3d *unknown*
10002d7c: 20 28 2d 35 *unknown*
10002d80: 2a 2d 31 33 *unknown*
10002d84: 29 00 76 61 *unknown*
10002d88: 72 20 3d 3d *unknown*
10002d8c: 20 28 2d 31 *unknown*
10002d90: 32 33 31 32 *unknown*
10002d94: 33 34 31 35 *unknown*
10002d98: 2a 39 36 36 *unknown*
10002d9c: 34 35 36 33 *unknown*
10002da0: 29 00 33 2e *unknown*
10002da4: 20 44 69 76 *unknown*
10002da8: 69 64 65 0a *unknown*
10002dac: 00 76 61 72 l.j 11d9b374 <_end+0x1d97364>
10002db0: 20 3d 3d 20 *unknown*
10002db4: 32 37 39 36 *unknown*
10002db8: 00 76 61 72 l.j 11d9b380 <_end+0x1d97370>
10002dbc: 20 3d 3d 20 *unknown*
10002dc0: 39 36 00 76 *unknown*
10002dc4: 61 72 20 3d *unknown*
10002dc8: 3d 20 2d 36 *unknown*
10002dcc: 37 00 34 2e *unknown*
10002dd0: 20 53 68 69 *unknown*
10002dd4: 66 74 20 6c *unknown*
10002dd8: 65 66 74 0a *unknown*
10002ddc: 00 76 61 72 l.j 11d9b3a4 <_end+0x1d97394>
10002de0: 20 3d 3d 20 *unknown*
10002de4: 30 78 38 30 *unknown*
10002de8: 30 30 30 30 *unknown*
10002dec: 30 30 00 35 *unknown*
10002df0: 2e 20 53 68 *unknown*
10002df4: 69 66 74 20 *unknown*
10002df8: 72 69 67 68 *unknown*
10002dfc: 74 0a 00 75 *unknown*
10002e00: 76 61 72 20 *unknown*
10002e04: 3d 3d 20 30 *unknown*
10002e08: 78 34 30 30 *unknown*
10002e0c: 30 30 30 30 *unknown*
10002e10: 30 00 75 76 *unknown*
10002e14: 61 72 20 3d *unknown*
10002e18: 3d 20 30 78 *unknown*
10002e1c: 30 30 30 30 *unknown*
10002e20: 30 30 30 31 *unknown*
10002e24: 00 36 2e 20 l.j 10d8e6a4 <_end+0xd8a694>
10002e28: 53 68 69 66 *unknown*
10002e2c: 74 20 72 69 *unknown*
10002e30: 67 68 74 20 *unknown*
10002e34: 61 72 69 74 *unknown*
10002e38: 68 6d 65 74 *unknown*
10002e3c: 69 63 0a 00 *unknown*
10002e40: 76 61 72 20 *unknown*
10002e44: 3d 3d 20 30 *unknown*
10002e48: 78 43 30 30 *unknown*
10002e4c: 30 30 30 30 *unknown*
10002e50: 30 00 37 2e *unknown*
10002e54: 20 53 69 67 *unknown*
10002e58: 6e 65 64 20 *unknown*
10002e5c: 63 6f 6d 70 *unknown*
10002e60: 61 72 69 73 *unknown*
10002e64: 69 6f 6e 0a *unknown*
10002e68: 00 76 61 72 l.j 11d9b430 <_end+0x1d97420>
10002e6c: 20 3c 20 31 *unknown*
10002e70: 00 76 61 72 l.j 11d9b438 <_end+0x1d97428>
10002e74: 20 3c 20 78 *unknown*
10002e78: 00 21 28 76 l.j 1084d050 <_end+0x849040>
10002e7c: 61 72 20 3e *unknown*
10002e80: 20 78 29 00 *unknown*
10002e84: 76 61 72 20 *unknown*
10002e88: 3e 20 78 00 *unknown*
10002e8c: 78 20 3c 3d *unknown*
10002e90: 20 76 61 72 *unknown*
10002e94: 00 38 2e 20 l.j 10e0e714 <_end+0xe0a704>
10002e98: 57 6f 72 64 *unknown*
10002e9c: 20 61 63 63 *unknown*
10002ea0: 65 73 73 0a *unknown*
10002ea4: 00 75 76 61 l.j 11d60828 <_end+0x1d5c818>
10002ea8: 72 20 3d 3d *unknown*
10002eac: 20 30 78 31 *unknown*
10002eb0: 32 33 34 35 *unknown*
10002eb4: 36 37 38 00 *unknown*
10002eb8: 73 77 20 3d *unknown*
10002ebc: 3d 20 30 78 *unknown*
10002ec0: 35 36 37 38 *unknown*
10002ec4: 00 2a 70 73 l.j 10a9f090 <_end+0xa9b080>
10002ec8: 77 2b 2b 20 *unknown*
10002ecc: 3d 3d 20 30 *unknown*
10002ed0: 78 31 32 33 *unknown*
10002ed4: 34 00 2a 70 *unknown*
10002ed8: 73 77 2b 2b *unknown*
10002edc: 20 3d 3d 20 *unknown*
10002ee0: 30 78 35 36 *unknown*
10002ee4: 37 38 00 2a *unknown*
10002ee8: 70 73 77 2b *unknown*
10002eec: 2b 20 3d 3d *unknown*
10002ef0: 20 30 78 63 *unknown*
10002ef4: 61 66 65 00 *unknown*
10002ef8: 2a 70 73 77 *unknown*
10002efc: 2b 2b 20 3d *unknown*
10002f00: 3d 20 30 78 *unknown*
10002f04: 62 61 62 65 *unknown*
10002f08: 00 39 2e 20 l.j 10e4e788 <_end+0xe4a778>
10002f0c: 42 79 74 65 *unknown*
10002f10: 20 61 63 63 *unknown*
10002f14: 65 73 73 0a *unknown*
10002f18: 00 73 62 20 l.j 11cdb798 <_end+0x1cd7788>
10002f1c: 3d 3d 20 30 *unknown*
10002f20: 78 37 38 00 *unknown*
10002f24: 2a 70 73 62 *unknown*
10002f28: 2b 2b 20 3d *unknown*
10002f2c: 3d 20 30 78 *unknown*
10002f30: 31 32 00 2a *unknown*
10002f34: 70 73 62 2b *unknown*
10002f38: 2b 20 3d 3d *unknown*
10002f3c: 20 30 78 33 *unknown*
10002f40: 34 00 2a 70 *unknown*
10002f44: 73 62 2b 2b *unknown*
10002f48: 20 3d 3d 20 *unknown*
10002f4c: 30 78 35 36 *unknown*
10002f50: 00 2a 70 73 l.j 10a9f11c <_end+0xa9b10c>
10002f54: 62 2b 2b 20 *unknown*
10002f58: 3d 3d 20 30 *unknown*
10002f5c: 78 37 38 00 *unknown*
10002f60: 75 76 61 72 *unknown*
10002f64: 20 3d 3d 20 *unknown*
10002f68: 30 78 61 62 *unknown*
10002f6c: 33 34 35 36 *unknown*
10002f70: 37 38 00 75 *unknown*
10002f74: 76 61 72 20 *unknown*
10002f78: 3d 3d 20 30 *unknown*
10002f7c: 78 61 62 63 *unknown*
10002f80: 64 35 36 37 *unknown*
10002f84: 38 00 75 76 *unknown*
10002f88: 61 72 20 3d *unknown*
10002f8c: 3d 20 30 78 *unknown*
10002f90: 61 62 63 64 *unknown*
10002f94: 65 66 37 38 *unknown*
10002f98: 00 75 76 61 l.j 11d6091c <_end+0x1d5c90c>
10002f9c: 72 20 3d 3d *unknown*
10002fa0: 20 30 78 61 *unknown*
10002fa4: 62 63 64 65 *unknown*
10002fa8: 66 30 31 00 *unknown*
10002fac: 31 30 2e 20 *unknown*
10002fb0: 43 6f 6d 70 *unknown*
10002fb4: 61 72 69 73 *unknown*
10002fb8: 69 6f 6e 0a *unknown*
10002fbc: 00 2d 20 49 l.j 10b4b0e0 <_end+0xb470d0>
10002fc0: 6e 63 6f 72 *unknown*
10002fc4: 72 65 63 74 *unknown*
10002fc8: 20 63 6f 6d *unknown*
10002fcc: 70 61 72 69 *unknown*
10002fd0: 73 69 6f 6e *unknown*
10002fd4: 0a 00 00 00 *unknown*
/rtl/sim/ram.v
0,0 → 1,113
//-----------------------------------------------------------------
// Module: ram - dual port block RAM
//-----------------------------------------------------------------
module ram
(
// Port A
input clka_i /*verilator public*/,
input ena_i /*verilator public*/,
input [3:0] wea_i /*verilator public*/,
input [31:2] addra_i /*verilator public*/,
input [31:0] dataa_i /*verilator public*/,
output [31:0] dataa_o /*verilator public*/,
 
// Port B
input clkb_i /*verilator public*/,
input enb_i /*verilator public*/,
input [3:0] web_i /*verilator public*/,
input [31:2] addrb_i /*verilator public*/,
input [31:0] datab_i /*verilator public*/,
output [31:0] datab_o /*verilator public*/
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter [31:0] block_count = 6;
parameter [31:0] SIZE = 14;
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
 
ram_dp8
#(
.WIDTH(8),
.SIZE(SIZE)
)
u0
(
.aclk_i(clka_i),
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[7:0]),
.adat_i(dataa_i[7:0]),
.awr_i(wea_i[0]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[7:0]),
.bdat_i(datab_i[7:0]),
.bwr_i(web_i[0])
);
 
ram_dp8
#(
.WIDTH(8),
.SIZE(SIZE)
)
u1
(
.aclk_i(clka_i),
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[15:8]),
.adat_i(dataa_i[15:8]),
.awr_i(wea_i[1]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[15:8]),
.bdat_i(datab_i[15:8]),
.bwr_i(web_i[1])
);
 
ram_dp8
#(
.WIDTH(8),
.SIZE(SIZE)
)
u2
(
.aclk_i(clka_i),
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[23:16]),
.adat_i(dataa_i[23:16]),
.awr_i(wea_i[2]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[23:16]),
.bdat_i(datab_i[23:16]),
.bwr_i(web_i[2])
);
 
ram_dp8
#(
.WIDTH(8),
.SIZE(SIZE)
)
u3
(
.aclk_i(clka_i),
.aadr_i(addra_i[SIZE+2-1:2]),
.adat_o(dataa_o[31:24]),
.adat_i(dataa_i[31:24]),
.awr_i(wea_i[3]),
.bclk_i(clkb_i),
.badr_i(addrb_i[SIZE+2-1:2]),
.bdat_o(datab_o[31:24]),
.bdat_i(datab_i[31:24]),
.bwr_i(web_i[3])
);
 
endmodule
/rtl/sim/top.cpp
0,0 → 1,232
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
 
#include "top_if.h"
 
#include "Vtop__Syms.h"
#include "verilated.h"
 
#if VM_TRACE
#include <verilated_vcd_c.h>
#endif
 
//-----------------------------------------------------------------
// Defines
//-----------------------------------------------------------------
#define MEMORY_START 0x10000000
#define MEMORY_SIZE (1024 * 1024)
 
#define OR32_BUBBLE_OPCODE 0xFC000000
 
#define CPU_INSTANCE top->v->u_cpu->u1_cpu
 
//-----------------------------------------------------------------
// Locals
//-----------------------------------------------------------------
static Vtop *top;
static unsigned int _stop_pc = 0xFFFFFFFF;
 
#if VM_TRACE
static unsigned int main_time = 0;
static VerilatedVcdC* tfp;
#endif
 
//-----------------------------------------------------------------
// top_init
//-----------------------------------------------------------------
int top_init(void)
{
top = new Vtop();
 
#if VM_TRACE
// If verilator was invoked with --trace
Verilated::traceEverOn(true);
VL_PRINTF("Enabling GTKWave Trace Output...\n");
tfp = new VerilatedVcdC;
top->trace (tfp, 99);
tfp->open ("wave_dump.vcd");
#endif
 
// Initial
top->clk_i = 0;
top->rst_i = 1;
top->intr_i = 0;
top->eval();
 
// Reset
top->clk_i = 1;
top->rst_i = 1;
top->eval();
 
top->clk_i = 0;
top->rst_i = 0;
top->eval();
 
return 0;
}
 
//-----------------------------------------------------------------
// top_load
//-----------------------------------------------------------------
int top_load(unsigned int addr, unsigned char val)
{
if (addr >= (MEMORY_SIZE - MEMORY_START))
return -1;
 
addr -= MEMORY_START;
 
switch (addr & 0x3)
{
case 0:
top->v->u_ram->u3->ram[addr >> 2] = val;
break;
case 1:
top->v->u_ram->u2->ram[addr >> 2] = val;
break;
case 2:
top->v->u_ram->u1->ram[addr >> 2] = val;
break;
case 3:
top->v->u_ram->u0->ram[addr >> 2] = val;
break;
}
 
return 0;
}
//-----------------------------------------------------------------
// top_setbreakpoint
//-----------------------------------------------------------------
int top_setbreakpoint(int bp, unsigned int pc)
{
if (bp != 0)
return -1;
else
{
_stop_pc = pc;
return 0;
}
}
//-----------------------------------------------------------------
// top_run
//-----------------------------------------------------------------
int top_run(unsigned int pc, int cycles, int intr_after_cycles)
{
int current_cycle = 0;
 
// Run until fault or number of cycles completed
while (!Verilated::gotFinish() && !top->fault_o && (current_cycle < cycles || cycles == -1))
{
// CLK->L
top->clk_i = 0;
top->eval();
 
#if VM_TRACE
if (tfp) tfp->dump (main_time++);
#endif
 
// CLK->H
top->clk_i = 1;
top->eval();
 
#if VM_TRACE
if (tfp) tfp->dump (main_time++);
#endif
 
// Get current executing instruction PC
unsigned int pc = CPU_INSTANCE->u_exec->get_pc_ex();
unsigned int opcode = CPU_INSTANCE->u_exec->get_opcode_ex();
 
#ifdef INST_TRACE
// Instruction trace - decode instruction opcode to text
if (opcode != OR32_BUBBLE_OPCODE)
printf("%08x: %02x %02x %02x %02x\n", pc, (opcode >> 24) & 0xFF, (opcode >> 16) & 0xFF, (opcode >> 8) & 0xFF, (opcode >> 0) & 0xFF);
#endif
 
// Generate interrupt after a certain number of cycles?
if (intr_after_cycles >= 0 && intr_after_cycles == current_cycle)
{
top->intr_i = 1;
intr_after_cycles = -1;
}
else
top->intr_i = 0;
 
current_cycle++;
 
// Breakpoint hit?
if (_stop_pc == pc || top->break_o)
{
if (_stop_pc == pc)
printf("Stopped at breakpoint 0x%x\n", _stop_pc);
printf("Cycles = %d\n", current_cycle);
return TOP_RES_BREAKPOINT;
}
}
 
printf("Cycles = %d\n", current_cycle);
 
// Fault
if (top->fault_o)
{
printf("FAULT PC %x!\n", CPU_INSTANCE->u_exec->get_pc_ex());
return TOP_RES_FAULT;
}
// Number of cycles reached
else if (current_cycle >= cycles)
return TOP_RES_MAX_CYCLES;
// No error
else
return TOP_RES_OK;
}
//-----------------------------------------------------------------
// top_done
//-----------------------------------------------------------------
void top_done(void)
{
top->final();
#if VM_TRACE
if (tfp)
{
tfp->close();
tfp = NULL;
}
#endif
}
/rtl/sim/main.cpp
0,0 → 1,258
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
 
#include "top_if.h"
#include "verilated.h"
 
#ifdef INCLUDE_ELF_SUPPORT
#include <libelf.h>
#include <fcntl.h>
#include <gelf.h>
#endif
 
//-----------------------------------------------------------------
// Defines
//-----------------------------------------------------------------
#define MEM_BASE 0x10000000
#define MEM_EXEC_OFFSET 0x100
 
//-----------------------------------------------------------------
// Locals
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// elf_load
//-----------------------------------------------------------------
#ifdef INCLUDE_ELF_SUPPORT
static int elf_load(const char *filename, unsigned int *startAddr)
{
int fd;
Elf * e;
Elf_Kind ek;
Elf_Scn *scn;
Elf_Data *data;
Elf32_Shdr *shdr;
size_t shstrndx;
 
if (elf_version ( EV_CURRENT ) == EV_NONE)
return 0;
 
if ((fd = open ( filename , O_RDONLY , 0)) < 0)
return 0;
 
if ((e = elf_begin ( fd , ELF_C_READ, NULL )) == NULL)
return 0;
ek = elf_kind ( e );
if (ek != ELF_K_ELF)
return 0;
 
// Get section name header index
if (elf_getshdrstrndx(e, &shstrndx)!=0)
return 0;
 
int section_idx = 0;
while ((scn = elf_getscn(e, section_idx)) != NULL)
{
shdr = elf32_getshdr(scn);
 
// Section which need loading (.text, .bss, .data, etc)
if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) &&
(shdr->sh_flags & SHF_EXECINSTR || shdr->sh_flags & SHF_ALLOC)
)
{
data = elf_getdata(scn, NULL);
 
// .text section?
if (elf_strptr(e, shstrndx, shdr->sh_name) && startAddr &&
strcmp(elf_strptr(e, shstrndx, shdr->sh_name), ".text") == 0)
{
*startAddr = shdr->sh_addr + MEM_EXEC_OFFSET;
}
 
printf("Memory: 0x%x - 0x%x (Size=%dKB) [%s]\n", shdr->sh_addr, shdr->sh_addr + shdr->sh_size - 1, shdr->sh_size / 1024, elf_strptr(e, shstrndx, shdr->sh_name));
 
if (shdr->sh_type == SHT_PROGBITS)
{
int i;
for (i=0;i<shdr->sh_size;i++)
top_load(shdr->sh_addr + i, ((unsigned char*)data->d_buf)[i]);
}
}
 
section_idx++;
}
 
elf_end ( e );
close ( fd );
return 1;
}
#endif
 
//-----------------------------------------------------------------
// main
//-----------------------------------------------------------------
int main(int argc, char **argv, char **env)
{
int c;
int err;
unsigned int loadAddr = MEM_BASE;
unsigned int execAddr = MEM_BASE + MEM_EXEC_OFFSET;
unsigned int breakAddr = 0xFFFFFFFF;
char *filename = NULL;
int help = 0;
int exitcode = 0;
int cycles = -1;
int intr_after = -1;
 
Verilated::commandArgs(argc, argv);
 
while ((c = getopt (argc, argv, "f:l:c:i:b:e:")) != -1)
{
switch(c)
{
case 'l':
loadAddr = strtoul(optarg, NULL, 0);
break;
case 'f':
filename = optarg;
break;
case 'c':
cycles = strtoul(optarg, NULL, 0);
break;
case 'i':
intr_after = strtoul(optarg, NULL, 0);
break;
case 'b':
breakAddr = strtoul(optarg, NULL, 0);
break;
case '?':
default:
help = 1;
break;
}
}
 
if (loadAddr < MEM_BASE)
{
fprintf (stderr,"Load address incorrect (0x%x)\n", loadAddr);
exit(-1);
}
 
if (help || filename == NULL)
{
fprintf (stderr,"Usage:\n");
fprintf (stderr,"-t = Enable program trace\n");
fprintf (stderr,"-l 0xnnnn = Executable load address\n");
fprintf (stderr,"-f filename = Executable to load\n");
fprintf (stderr,"-c num = Max number of cycles\n");
fprintf (stderr,"-i num = Generate interrupt after num cycles\n");
fprintf (stderr,"-b addr = Break at address\n");
exit(0);
}
 
top_init();
 
if (strstr(filename, ".elf"))
{
#ifdef INCLUDE_ELF_SUPPORT
if (!elf_load(filename, &execAddr))
{
fprintf (stderr,"Error: Could not open ELF file %s\n", filename);
exit(-1);
}
#else
fprintf (stderr,"Error: ELF files not supported\n");
exit(-1);
#endif
}
else
{
FILE *f;
 
printf("Opening %s\n", filename);
f = fopen(filename, "rb");
if (f)
{
long size;
char *buf;
 
// Get size
fseek(f, 0, SEEK_END);
size = ftell(f);
rewind(f);
 
buf = (char*)malloc(size+1);
if (buf)
{
unsigned int addr;
 
// Read file data in
int len = fread(buf, 1, size, f);
buf[len] = 0;
 
printf("Loading to 0x%x\n", loadAddr);
for (addr=0;addr<len;addr++)
top_load(loadAddr + addr, buf[addr]);
 
free(buf);
fclose(f);
}
}
else
{
printf("Could not read file!\n");
exit(-1);
}
}
 
// Setup breakpoint to stop at (or 0xFFFFFFFF if none)
top_setbreakpoint(0, breakAddr);
 
// Run
err = top_run(execAddr, cycles, intr_after);
 
// Cleanup
top_done();
 
printf("Exit\n");
exit((err == TOP_RES_FAULT) ? 1 : 0);
}
/rtl/sim/top.v
0,0 → 1,227
//-----------------------------------------------------------------
// AltOR32
// Alternative Lightweight OpenRisc
// V2.0
// Ultra-Embedded.com
// Copyright 2011 - 2013
//
// Email: admin@ultra-embedded.com
//
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
// removed from the file and that any derivative work contains
// the original copyright notice and the associated disclaimer.
//
// This source file is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any
// later version.
//
// This source is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General
// Public License along with this source; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Module
//-----------------------------------------------------------------
module top
(
// Clocking & Reset
input clk_i,
input rst_i,
// Fault Output
output fault_o,
// Break Output
output break_o,
// Interrupt Input
input intr_i
);
 
//-----------------------------------------------------------------
// Params
//-----------------------------------------------------------------
parameter CLK_KHZ = 8192;
parameter BOOT_VECTOR = 32'h10000000;
parameter ISR_VECTOR = 32'h10000000;
 
//-----------------------------------------------------------------
// Registers / Wires
//-----------------------------------------------------------------
wire [31:0] soc_addr;
wire [31:0] soc_data_w;
wire [31:0] soc_data_r;
wire [3:0] soc_wr;
wire soc_rd;
wire soc_irq;
 
wire[31:0] dmem_address;
wire[31:0] dmem_data_w;
wire[31:0] dmem_data_r;
wire[3:0] dmem_wr;
wire dmem_rd;
wire dmem_burst;
wire dmem_ack;
reg dmem_req_r;
 
wire[31:0] imem_addr;
wire[31:0] imem_data;
wire imem_rd;
wire imem_burst;
wire imem_ack;
reg imem_req_r;
 
//-----------------------------------------------------------------
// Instantiation
//-----------------------------------------------------------------
 
// BlockRAM
ram
#(
.block_count(128) // 1MB
)
u_ram
(
.clka_i(clk_i),
.ena_i(1'b1),
.wea_i(4'b0),
.addra_i(imem_addr[31:2]),
.dataa_i(32'b0),
.dataa_o(imem_data),
 
.clkb_i(clk_i),
.enb_i(1'b1),
.web_i(dmem_wr),
.addrb_i(dmem_address[31:2]),
.datab_i(dmem_data_w),
.datab_o(dmem_data_r)
);
 
 
// CPU
cpu_if
#(
.CLK_KHZ(CLK_KHZ),
.BOOT_VECTOR(32'h10000000),
.ISR_VECTOR(32'h10000000),
.ENABLE_ICACHE("ENABLED"),
.ENABLE_DCACHE("ENABLED"),
.REGISTER_FILE_TYPE("SIMULATION")
)
u_cpu
(
// General - clocking & reset
.clk_i(clk_i),
.rst_i(rst_i),
.fault_o(fault_o),
.break_o(break_o),
.nmi_i(1'b0),
.intr_i(soc_irq),
 
// Instruction Memory 0 (0x10000000 - 0x10FFFFFF)
.imem0_addr_o(imem_addr),
.imem0_rd_o(imem_rd),
.imem0_burst_o(imem_burst),
.imem0_data_in_i(imem_data),
.imem0_accept_i(1'b1),
.imem0_ack_i(imem_ack),
 
// Data Memory 0 (0x10000000 - 0x10FFFFFF)
.dmem0_addr_o(dmem_address),
.dmem0_data_o(dmem_data_w),
.dmem0_data_i(dmem_data_r),
.dmem0_wr_o(dmem_wr),
.dmem0_rd_o(dmem_rd),
.dmem0_accept_i(1'b1),
.dmem0_burst_o(dmem_burst),
.dmem0_ack_i(dmem_ack),
// Data Memory 1 (0x11000000 - 0x11FFFFFF)
.dmem1_addr_o(),
.dmem1_data_o(),
.dmem1_data_i(32'b0),
.dmem1_wr_o(),
.dmem1_rd_o(),
.dmem1_accept_i(1'b1),
.dmem1_burst_o(/*open*/),
.dmem1_ack_i(1'b1),
 
// Data Memory 2 (0x12000000 - 0x12FFFFFF)
.dmem2_addr_o(soc_addr),
.dmem2_data_o(soc_data_w),
.dmem2_data_i(soc_data_r),
.dmem2_wr_o(soc_wr),
.dmem2_rd_o(soc_rd),
.dmem2_accept_i(1'b1),
.dmem2_burst_o(/*open*/),
.dmem2_ack_i(1'b1)
);
 
// CPU SOC
soc
#(
.CLK_KHZ(CLK_KHZ),
.ENABLE_SYSTICK_TIMER("ENABLED"),
.ENABLE_HIGHRES_TIMER("ENABLED"),
.EXTERNAL_INTERRUPTS(1)
)
u_soc
(
// General - clocking & reset
.clk_i(clk_i),
.rst_i(rst_i),
.ext_intr_i(1'b0),
.intr_o(soc_irq),
 
// Memory Port
.io_addr_i(soc_addr),
.io_data_i(soc_data_w),
.io_data_o(soc_data_r),
.io_wr_i(soc_wr),
.io_rd_i(soc_rd)
);
 
// Ack
always @(posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
imem_req_r <= 1'b0;
end
else
begin
imem_req_r <= imem_rd;
end
end
 
assign imem_ack = imem_req_r;
 
// Ack
always @(posedge clk_i or posedge rst_i)
begin
if (rst_i == 1'b1)
begin
dmem_req_r <= 1'b0;
end
else
begin
dmem_req_r <= dmem_rd | (|dmem_wr);
end
end
 
assign dmem_ack = dmem_req_r;
endmodule
/rtl/sim/top_if.h
0,0 → 1,21
#ifndef __TOP_IF_H__
#define __TOP_IF_H__
 
//--------------------------------------------------------------------
// Defines
//--------------------------------------------------------------------
#define TOP_RES_FAULT -1
#define TOP_RES_OK 0
#define TOP_RES_MAX_CYCLES 1
#define TOP_RES_BREAKPOINT 2
 
//--------------------------------------------------------------------
// Prototypes
//--------------------------------------------------------------------
int top_init(void);
int top_load(unsigned int addr, unsigned char val);
void top_done(void);
int top_run(unsigned int pc, int cycles, int intr_after_cycles);
int top_setbreakpoint(int bp, unsigned int pc);
 
#endif
/rtl/sim/test_image.elf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
rtl/sim/test_image.elf Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rtl/sim/test_image.bin =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rtl/sim/test_image.bin =================================================================== --- rtl/sim/test_image.bin (nonexistent) +++ rtl/sim/test_image.bin (revision 27)
rtl/sim/test_image.bin Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rtl/sim/makefile =================================================================== --- rtl/sim/makefile (nonexistent) +++ rtl/sim/makefile (revision 27) @@ -0,0 +1,67 @@ + +# Default binary to load & run +TEST_IMAGE ?= test_image.bin +SIMARGS ?= +CYCLES ?= -1 +STOP_AT ?= 0xFFFFFFFF + +# Default core to simulate +RTL_CORE ?= cpu +CORE_FILENAME ?= altor32.v + +# Waveform trace disabled by default +TRACE?= 0 + +# Enable debug output +DEBUG?= 0 + +# Enable instruction trace +INST_TRACE?= 0 + +# Top module (without .v extension) +TOP_MODULE = top + +# Additional modules which can't be auto found +ADDITIONAL_MODULES = ../$(RTL_CORE)/$(CORE_FILENAME) + +# CPP Source Files +SRC_CPP = main.cpp top.cpp + +# Source directories +INC_DIRS = -I../$(RTL_CORE) -I../soc -I../peripheral + +# Build directory +BUILD_DIR = build + +VERILATOR_OPTS = + +ifeq ($(TRACE),1) + VERILATOR_OPTS += --trace +endif + +ifeq ($(DEBUG),1) + VERILATOR_OPTS += +define+CONF_CORE_DEBUG+ +endif + +ifeq ($(INST_TRACE),1) + VERILATOR_OPTS += -CFLAGS "-DINST_TRACE" +endif + +VERILATOR_OPTS += +define+SIMULATION+ + +all: run + +compile: clean + verilator --cc $(TOP_MODULE).v $(ADDITIONAL_MODULES) $(SRC_CPP) $(INC_DIRS) +define+CONF_TARGET_SIM+ --exe -Mdir $(BUILD_DIR) $(VERILATOR_OPTS) + make -j -f V$(TOP_MODULE).mk -C $(BUILD_DIR) + +run: compile + ./$(BUILD_DIR)/V$(TOP_MODULE) -b $(STOP_AT) -c $(CYCLES) -f $(TEST_IMAGE) $(SIMARGS) + +ifeq ($(TRACE),1) +view: + gtkwave wave_dump.vcd gtksettings.sav +endif + +clean : + -rm -rf $(BUILD_DIR) wave_dump.vcd Index: rtl/sim/ram_dp8.v =================================================================== --- rtl/sim/ram_dp8.v (nonexistent) +++ rtl/sim/ram_dp8.v (revision 27) @@ -0,0 +1,74 @@ + +//----------------------------------------------------------------- +// Module: ram_dp8 - dual port block RAM +//----------------------------------------------------------------- +module ram_dp8 +( + aclk_i, + aadr_i, + adat_i, + awr_i, + adat_o, + + bclk_i, + badr_i, + bdat_i, + bwr_i, + bdat_o +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] WIDTH = 8; +parameter [31:0] SIZE = 14; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input aclk_i /*verilator public*/; +output [(WIDTH - 1):0] adat_o /*verilator public*/; +input [(WIDTH - 1):0] adat_i /*verilator public*/; +input [(SIZE - 1):0] aadr_i /*verilator public*/; +input awr_i /*verilator public*/; +input bclk_i /*verilator public*/; +output [(WIDTH - 1):0] bdat_o /*verilator public*/; +input [(WIDTH - 1):0] bdat_i /*verilator public*/; +input [(SIZE - 1):0] badr_i /*verilator public*/; +input bwr_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +/* verilator lint_off MULTIDRIVEN */ +reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/; +/* verilator lint_on MULTIDRIVEN */ + +reg [(SIZE - 1):0] rd_addr_a; +reg [(SIZE - 1):0] rd_addr_b; +wire [(WIDTH - 1):0] adat_o; +wire [(WIDTH - 1):0] bdat_o; + +//----------------------------------------------------------------- +// Processes +//----------------------------------------------------------------- +always @ (posedge aclk_i) +begin + if (awr_i == 1'b1) + ram[aadr_i] <= adat_i; + rd_addr_a <= aadr_i; +end +always @ (posedge bclk_i) +begin + if (bwr_i == 1'b1) + ram[badr_i] <= bdat_i; + rd_addr_b <= badr_i; +end + +//------------------------------------------------------------------- +// Combinatorial +//------------------------------------------------------------------- +assign adat_o = ram[rd_addr_a]; +assign bdat_o = ram[rd_addr_b]; + +endmodule Index: rtl/peripheral/intr_defs.v =================================================================== --- rtl/peripheral/intr_defs.v (nonexistent) +++ rtl/peripheral/intr_defs.v (revision 27) @@ -0,0 +1,44 @@ +//----------------------------------------------------------------- +// AltOR32 +// Alternative Lightweight OpenRisc +// V2.0 +// Ultra-Embedded.com +// Copyright 2011 - 2013 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2013 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +`define IRQ_MASK_SET 8'h00 +`define IRQ_MASK_CLR 8'h04 +`define IRQ_STATUS 8'h08 + `define IRQ_EXT_FIRST (8) Index: rtl/peripheral/timer_defs.v =================================================================== --- rtl/peripheral/timer_defs.v (nonexistent) +++ rtl/peripheral/timer_defs.v (revision 27) @@ -0,0 +1,42 @@ +//----------------------------------------------------------------- +// AltOR32 +// Alternative Lightweight OpenRisc +// V2.0 +// Ultra-Embedded.com +// Copyright 2011 - 2013 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2013 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +`define TIMER_SYSTICK_VAL 8'h00 +`define TIMER_HIRES 8'h04 Index: rtl/peripheral/intr_periph.v =================================================================== --- rtl/peripheral/intr_periph.v (nonexistent) +++ rtl/peripheral/intr_periph.v (revision 27) @@ -0,0 +1,230 @@ +//----------------------------------------------------------------- +// AltOR32 +// Alternative Lightweight OpenRisc +// V2.0 +// Ultra-Embedded.com +// Copyright 2011 - 2013 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2013 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "intr_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module intr_periph +( + // General - Clocking & Reset + clk_i, + rst_i, + intr_o, + + // Interrupts + intr0_i, + intr1_i, + intr2_i, + intr3_i, + intr4_i, + intr5_i, + intr6_i, + intr7_i, + intr_ext_i, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter EXTERNAL_INTERRUPTS = 1; +parameter INTERRUPT_COUNT = EXTERNAL_INTERRUPTS + 8; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; +output intr_o /*verilator public*/; + +input intr0_i /*verilator public*/; +input intr1_i /*verilator public*/; +input intr2_i /*verilator public*/; +input intr3_i /*verilator public*/; +input intr4_i /*verilator public*/; +input intr5_i /*verilator public*/; +input intr6_i /*verilator public*/; +input intr7_i /*verilator public*/; +input [(EXTERNAL_INTERRUPTS - 1):0] intr_ext_i /*verilator public*/; +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- +reg [31:0] data_o; +reg intr_o; + +// IRQ Status +wire intr_in; +reg [INTERRUPT_COUNT-1:0] irq_status; +reg [INTERRUPT_COUNT-1:0] irq_mask; +reg [INTERRUPT_COUNT-1:0] v_irq_status; + +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + irq_status <= {(INTERRUPT_COUNT){1'b0}}; + irq_mask <= {(INTERRUPT_COUNT){1'b0}}; + intr_o <= 1'b0; + end + else + begin + + // Get current IRQ status + v_irq_status = irq_status; + + // IRQ0 + if (intr0_i == 1'b1) + v_irq_status[0] = 1'b1; + + // IRQ1 + if (intr1_i == 1'b1) + v_irq_status[1] = 1'b1; + + // IRQ2 + if (intr2_i == 1'b1) + v_irq_status[2] = 1'b1; + + // IRQ3 + if (intr3_i == 1'b1) + v_irq_status[3] = 1'b1; + + // IRQ4 + if (intr4_i == 1'b1) + v_irq_status[4] = 1'b1; + + // IRQ5 + if (intr5_i == 1'b1) + v_irq_status[5] = 1'b1; + + // IRQ6 + if (intr6_i == 1'b1) + v_irq_status[6] = 1'b1; + + // IRQ7 + if (intr7_i == 1'b1) + v_irq_status[7] = 1'b1; + + // External interrupts + begin : ext_ints_loop + integer i; + for (i=0; i< EXTERNAL_INTERRUPTS; i=i+1) + begin + if (intr_ext_i[i] == 1'b1) + v_irq_status[(`IRQ_EXT_FIRST + i)] = 1'b1; + end + end + + // Update IRQ status + irq_status <= v_irq_status; + + // Generate interrupt based on masked status + intr_o <= ((v_irq_status & irq_mask) != {(INTERRUPT_COUNT){1'b0}}) ? 1'b1 : 1'b0; + + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `IRQ_MASK_SET : + irq_mask <= (irq_mask | data_i[INTERRUPT_COUNT-1:0]); + + `IRQ_MASK_CLR : + irq_mask <= (irq_mask & ~ (data_i[INTERRUPT_COUNT-1:0])); + + `IRQ_STATUS : // (IRQ Acknowledge) + irq_status <= (v_irq_status & ~ (data_i[INTERRUPT_COUNT-1:0])); + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + end + else + begin + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + `IRQ_MASK_SET : + data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask}; + + `IRQ_MASK_CLR : + data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_mask}; + + `IRQ_STATUS : + data_o <= {{(32-INTERRUPT_COUNT){1'b0}}, irq_status}; + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +endmodule Index: rtl/peripheral/timer_periph.v =================================================================== --- rtl/peripheral/timer_periph.v (nonexistent) +++ rtl/peripheral/timer_periph.v (revision 27) @@ -0,0 +1,279 @@ +//----------------------------------------------------------------- +// AltOR32 +// Alternative Lightweight OpenRisc +// V2.0 +// Ultra-Embedded.com +// Copyright 2011 - 2013 +// +// Email: admin@ultra-embedded.com +// +// License: LGPL +//----------------------------------------------------------------- +// +// Copyright (C) 2011 - 2013 Ultra-Embedded.com +// +// This source file may be used and distributed without +// restriction provided that this copyright statement is not +// removed from the file and that any derivative work contains +// the original copyright notice and the associated disclaimer. +// +// This source file is free software; you can redistribute it +// and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any +// later version. +// +// This source is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied +// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the GNU Lesser General Public License for more +// details. +// +// You should have received a copy of the GNU Lesser General +// Public License along with this source; if not, write to the +// Free Software Foundation, Inc., 59 Temple Place, Suite 330, +// Boston, MA 02111-1307 USA +//----------------------------------------------------------------- + +//----------------------------------------------------------------- +// Includes +//----------------------------------------------------------------- +`include "timer_defs.v" + +//----------------------------------------------------------------- +// Module: +//----------------------------------------------------------------- +module timer_periph +( + // General - Clocking & Reset + clk_i, + rst_i, + + // Interrupts + intr_systick_o, + intr_hires_o, + + // Peripheral bus + addr_i, + data_o, + data_i, + wr_i, + rd_i +); + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +parameter [31:0] CLK_KHZ = 12288; +parameter SYSTICK_INTR_MS = 1; +parameter ENABLE_SYSTICK_TIMER = "ENABLED"; +parameter ENABLE_HIGHRES_TIMER = "ENABLED"; + +//----------------------------------------------------------------- +// I/O +//----------------------------------------------------------------- +input clk_i /*verilator public*/; +input rst_i /*verilator public*/; + +output intr_systick_o /*verilator public*/; +output intr_hires_o /*verilator public*/; + +input [7:0] addr_i /*verilator public*/; +output [31:0] data_o /*verilator public*/; +input [31:0] data_i /*verilator public*/; +input [3:0] wr_i /*verilator public*/; +input rd_i /*verilator public*/; + +//----------------------------------------------------------------- +// Registers / Wires +//----------------------------------------------------------------- + +reg [31:0] data_o; + +// Systick Timer +reg systick_event; +reg [31:0] systick_count; +reg [31:0] systick_clk_count; + +// Hi-res system clock tick counter +reg hr_timer_intr; +reg [31:0] hr_timer_cnt; +reg [31:0] hr_timer_match; + +//----------------------------------------------------------------- +// Systick +//----------------------------------------------------------------- +generate +if (ENABLE_SYSTICK_TIMER == "ENABLED") +begin + + // SysTick Timer (1 ms resolution) + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + systick_count <= 32'h00000000; + systick_clk_count <= 32'h00000000; + systick_event <= 1'b0; + end + else + begin + systick_event <= 1'b0; + + if (systick_clk_count == CLK_KHZ) + begin + systick_count <= (systick_count + 1); + systick_event <= 1'b1; + systick_clk_count <= 32'h00000000; + end + else + systick_clk_count <= (systick_clk_count + 1); + end + end + + // SysTick Interrupt + integer systick_event_count; + reg systick_event_intr; + + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + begin + systick_event_count <= 0; + systick_event_intr <= 1'b0; + end + else + begin + systick_event_intr <= 1'b0; + + if (systick_event) + begin + systick_event_count <= (systick_event_count + 1); + + if (systick_event_count == (SYSTICK_INTR_MS-1)) + begin + systick_event_intr <= 1'b1; + systick_event_count <= 0; + end + end + end + end + + assign intr_systick_o = systick_event_intr; +end +else +begin + // Systick disabled + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + systick_count <= 32'h00000000; + else + systick_count <= 32'h00000000; + end + + assign intr_systick_o = 1'b0; +end +endgenerate + +//----------------------------------------------------------------- +// Hi Resolution Timer +//----------------------------------------------------------------- +generate +if (ENABLE_HIGHRES_TIMER == "ENABLED") +begin + + always @ (posedge rst_i or posedge clk_i) + begin + if (rst_i == 1'b1) + begin + hr_timer_cnt <= 32'h00000000; + hr_timer_intr <= 1'b0; + end + else + begin + hr_timer_intr <= 1'b0; + + // Clock tick counter + hr_timer_cnt <= (hr_timer_cnt + 1); + + // Hi-res Timer IRQ + if ((hr_timer_match != 32'h00000000) && (hr_timer_match == hr_timer_cnt)) + hr_timer_intr <= 1'b1; + end + end + + assign intr_hires_o = hr_timer_intr; +end +else +begin + // Hi resolution timer disabled + always @ (posedge rst_i or posedge clk_i ) + begin + if (rst_i == 1'b1) + hr_timer_cnt <= 32'h00000000; + else + hr_timer_cnt <= 32'h00000000; + end + + assign intr_hires_o = 1'b0; +end +endgenerate +//----------------------------------------------------------------- +// Peripheral Register Write +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + hr_timer_match <= 32'h00000000; + end + else + begin + // Write Cycle + if (wr_i != 4'b0000) + begin + case (addr_i) + + `TIMER_HIRES : + hr_timer_match <= data_i; + + default : + ; + endcase + end + end +end + +//----------------------------------------------------------------- +// Peripheral Register Read +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + data_o <= 32'h00000000; + end + else + begin + // Read cycle? + if (rd_i == 1'b1) + begin + case (addr_i[7:0]) + + // 32-bit systick/1ms counter + `TIMER_SYSTICK_VAL : + data_o <= systick_count; + + // Hi res timer (clock rate) + `TIMER_HIRES : + data_o <= hr_timer_cnt; + + default : + data_o <= 32'h00000000; + endcase + end + end +end + +endmodule

powered by: WebSVN 2.1.0

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