mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 21:27:10 -04:00
Add ns16750 UART to Spike
This commit is contained in:
parent
c907270502
commit
0d6e4fe658
9 changed files with 151 additions and 48 deletions
|
@ -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
|
||||
|
|
|
@ -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 ),
|
||||
.*
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue