Add ns16750 UART to Spike

This commit is contained in:
Florian Zaruba 2018-11-04 11:39:15 +01:00
parent c907270502
commit 0d6e4fe658
No known key found for this signature in database
GPG key ID: E742FFE8EC38A792
9 changed files with 151 additions and 48 deletions

View file

@ -23,6 +23,7 @@ import ariane_pkg::*;
module decoder (
input logic [63:0] pc_i, // PC from IF
input logic is_compressed_i, // is a compressed instruction
input logic [15:0] compressed_instr_i, // compressed form of instruction
input logic is_illegal_i, // illegal compressed instruction
input logic [31:0] instruction_i, // instruction from IF
input branchpredict_sbe_t branch_predict_i,
@ -552,7 +553,7 @@ module decoder (
if (~ex_i.valid) begin
// if we didn't already get an exception save the instruction here as we may need it
// in the commit stage if we got a access exception to one of the CSR registers
instruction_o.ex.tval = {32'b0, instruction_i};
instruction_o.ex.tval = (is_compressed_i) ? {48'b0, compressed_instr_i} : {32'b0, instruction_i};
// instructions which will throw an exception are marked as valid
// e.g.: they can be committed anytime and do not need to wait for any functional unit
// check here if we decoded an invalid instruction or if the compressed decoder already decoded

View file

@ -82,14 +82,15 @@ module id_stage (
// 3. Decode and emit instruction to issue stage
// ---------------------------------------------------------
decoder decoder_i (
.pc_i ( fetch_entry.address ),
.is_compressed_i ( is_compressed ),
.instruction_i ( instruction ),
.branch_predict_i ( fetch_entry.branch_predict ),
.is_illegal_i ( is_illegal ),
.ex_i ( fetch_entry.ex ),
.instruction_o ( decoded_instruction ),
.is_control_flow_instr_o ( is_control_flow_instr ),
.pc_i ( fetch_entry.address ),
.is_compressed_i ( is_compressed ),
.compressed_instr_i ( fetch_entry.instruction[15:0] ),
.instruction_i ( instruction ),
.branch_predict_i ( fetch_entry.branch_predict ),
.is_illegal_i ( is_illegal ),
.ex_i ( fetch_entry.ex ),
.instruction_o ( decoded_instruction ),
.is_control_flow_instr_o ( is_control_flow_instr ),
.*
);

View file

@ -33,14 +33,15 @@ module spike #(
end
riscv::commit_log_t commit_log;
logic [31:0] instr;
always_ff @(posedge clk_i) begin
if (rst_ni) begin
for (int i = 0; i < ariane_pkg::NR_COMMIT_PORTS; i++) begin
if (commit_instr_i[i].valid && commit_ack_i[i]) begin
spike_tick(commit_log);
$display("\x1B[32m%h %h\x1B[0m", commit_log.pc, commit_log.instr);
$display("\x1B[37m%h %h\x1B[0m", commit_instr_i[i].pc, commit_instr_i[i].ex.tval);
instr = (commit_log.instr[1:0] != 2'b11) ? {16'b0, commit_log.instr[15:0]} : commit_log.instr;
$display("\x1B[32m%h %h\x1B[0m", commit_log.pc, instr);
$display("\x1B[37m%h %h\x1B[0m", commit_instr_i[i].pc, commit_instr_i[i].ex.tval[31:0]);
end
end
end

View file

@ -82,7 +82,15 @@ class uart_t : public abstract_device_t {
bool load(reg_t addr, size_t len, uint8_t* bytes);
bool store(reg_t addr, size_t len, const uint8_t* bytes);
private:
std::vector<char> procs;
uint8_t ier;
uint8_t dll;
uint8_t dlm;
uint8_t lcr;
uint8_t lsr;
uint8_t scr;
uint8_t msr;
uint8_t mcr;
bool fifo_enabled;
};
#endif

View file

@ -54,7 +54,7 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
" #address-cells = <2>;\n"
" #size-cells = <2>;\n"
" compatible = \"ucbbar,spike-bare-soc\", \"simple-bus\";\n"
" ranges;\n"
" ranges;\n"
" clint@" << CLINT_BASE << " {\n"
" compatible = \"riscv,clint0\";\n"
" interrupts-extended = <" << std::dec;
@ -67,8 +67,18 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
" 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n"
" };\n"
" };\n"
" htif {\n"
" compatible = \"ucb,htif0\";\n"
// " htif {\n"
// " compatible = \"ucb,htif0\";\n"
// " };\n"
" uart@" << UART_BASE << " {\n"
" compatible = \"ns16750\";\n"
" reg = <0x0 0x10000000 0x0 0x1000>;\n"
" clock-frequency = <50000000>;\n"
" current-speed = <115200>;\n"
// " interrupt-parent = <&PLIC0>;\n"
// " interrupts = <1>;\n"
" reg-shift = <2>;\n"
" reg-io-width = <4>;\n"
" };\n"
"};\n";
return s.str();

View file

@ -153,6 +153,8 @@
#define DEFAULT_RSTVEC 0x00010000
#define CLINT_BASE 0x02000000
#define CLINT_SIZE 0x000c0000
#define UART_BASE 0x10000000
#define UART_SIZE 0x00010000
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000

View file

@ -60,6 +60,8 @@ sim_t::sim_t(const char* isa, size_t nprocs, bool halted, reg_t start_pc,
clint.reset(new clint_t(procs));
bus.add_device(CLINT_BASE, clint.get());
uart.reset(new uart_t());
bus.add_device(UART_BASE, uart.get());
}
sim_t::~sim_t()

View file

@ -53,6 +53,7 @@ private:
std::string dts;
std::unique_ptr<rom_device_t> boot_rom;
std::unique_ptr<clint_t> clint;
std::unique_ptr<uart_t> uart;
bus_t bus;
processor_t* get_core(const std::string& i);

View file

@ -1,49 +1,126 @@
#include "devices.h"
#include "processor.h"
#define RBR 0
#define THR 0
#define IER 1
#define IIR 2
#define FCR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6
#define SCR 7
#define DLL 0
#define DLM 1
#define THRE 5 // transmit holding register empty
#define TEMT 6 // transmit holding register empty
uart_t::uart_t()
{
}
bool uart_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
// if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
// std::vector<msip_t> msip(procs.size());
// for (size_t i = 0; i < procs.size(); ++i)
// msip[i] = !!(procs[i]->state.mip & MIP_MSIP);
// memcpy(bytes, (uint8_t*)&msip[0] + addr - MSIP_BASE, len);
// } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
// memcpy(bytes, (uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, len);
// } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
// memcpy(bytes, (uint8_t*)&mtime + addr - MTIME_BASE, len);
// } else {
// return false;
// }
// we do not support unaligned stores
if ((addr & 0x3) != 0) {
return false;
}
switch ((addr >> 0x2) & 0x7) {
case THR:
// access DLL
if (lcr & 0x80) {
bytes[0] = dll;
} else {
// printf("%c", bytes[0]);
}
break;
case IER:
// access DLM
if (lcr & 0x80) {
bytes[0] = dlm;
} else {
bytes[0] = ier;
}
break;
case IIR:
if (fifo_enabled) {
bytes[0] = 0xC0;
} else {
bytes[0] = 0x00;
}
break;
case LCR:
bytes[0] = lcr;
break;
case MCR:
bytes[0] = mcr;
break;
case LSR:
bytes[0] = lsr | (1 << THRE) | (1 << TEMT);
break;
case MSR:
bytes[0] = msr;
break;
case SCR:
bytes[0] = scr;
break;
}
return true;
}
bool uart_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
// if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
// std::vector<msip_t> msip(procs.size());
// std::vector<msip_t> mask(procs.size(), 0);
// memcpy((uint8_t*)&msip[0] + addr - MSIP_BASE, bytes, len);
// memset((uint8_t*)&mask[0] + addr - MSIP_BASE, 0xff, len);
// for (size_t i = 0; i < procs.size(); ++i) {
// if (!(mask[i] & 0xFF)) continue;
// procs[i]->state.mip &= ~MIP_MSIP;
// if (!!(msip[i] & 1))
// procs[i]->state.mip |= MIP_MSIP;
// }
// } else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
// memcpy((uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, bytes, len);
// } else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
// memcpy((uint8_t*)&mtime + addr - MTIME_BASE, bytes, len);
// } else {
// return false;
// }
// increment(0);
// we do not support unaligned stores
if ((addr & 0x3) != 0) {
return false;
}
switch ((addr >> 0x2) & 0x7) {
case THR:
// access DLL
if (lcr & 0x80) {
dll = bytes[0];
} else {
printf("%c", bytes[0]);
}
break;
case IER:
// access DLM
if (lcr & 0x80) {
dlm = bytes[0];
} else {
ier = bytes[0] & 0xF;
}
break;
case FCR:
if (bytes[0] & 0x1) {
fifo_enabled = true;
} else {
fifo_enabled = false;
}
break;
case LCR:
lcr = bytes[0];
break;
case MCR:
mcr = bytes[0] & 0x1F;
break;
case LSR:
lsr = bytes[0];
break;
case MSR:
msr = bytes[0];
break;
case SCR:
scr = bytes[0];
break;
}
return true;
}