litex software build 32BE

pull/18/head
openpowerwtf 2 years ago
parent f48b4198d4
commit 78bd976bcc

@ -72,7 +72,7 @@ def _to_signal(obj):

class BaseSoC(SoCCore):

def __init__(self, sys_clk_freq=int(50e6),
def __init__(self, sys_clk_freq=int(100e6),
with_analyzer=False,
uart_baudrate=115200,
**kwargs):

@ -24,12 +24,12 @@ GAS_FLAGS = {
'WB_64LE' : '-defsym BIOS_LE=1'
}

#wtf skip crc and ram memtest for now!
GCC_FLAGS = {
'WB_32BE' : '-mcpu=a2 -m32 -mbig-endian -fno-stack-protector -Xassembler -defsym -Xassembler BIOS_32=1',
'WB_32BE' : '-mcpu=a2 -m32 -mbig-endian -fno-stack-protector -Xassembler -defsym -Xassembler BIOS_32=1 -DCONFIG_BIOS_NO_BOOT=1 -DCONFIG_BIOS_NO_CRC=1 -DCONFIG_MAIN_RAM_INIT=1',
'WB_64LE' : '-mcpu=a2 -m64 -mlittle-endian -mabi=elfv2 -fno-stack-protector -Xassembler -defsym -Xassembler BIOS_LE=1'
}


class A2O(CPU, AutoCSR):
name = 'a2o'
human_name = 'a2o'
@ -68,16 +68,17 @@ class A2O(CPU, AutoCSR):
variant = 'WB_64LE'

if variant == 'WB_32BE':
#self.family = 'ppc' # kills meson build
self.family = 'powerpc'
self.family = 'ppc' # kills meson build unless update meson.build file
#self.family = 'powerpc'
self.data_width = 32
self.endianness = 'big'
self.gcc_triple = 'powerpc-linux-gnu'
self.linker_output_format = 'elf32-powerpc'


self.platform = platform
self.variant = variant
self.human_name = CPU_VARIANTS.get(variant, 'a2o')
self.human_name = 'a2o_' + variant # CPU_VARIANTS.get(variant, 'a2o')
self.external_variant = None
self.reset = Signal()
self.interrupt = Signal(3)

@ -10,7 +10,7 @@
# litex boot kernel (original ppc-embedded architecture)
# resets to 32BE
# set up translations for starting bios (inc. BE/LE)
# copy modifiable rom data to ram - or do in bios?
# copy modifiable rom data to ram
# set up msr for running bios (inc. 32/64)
# jump to bios

@ -23,8 +23,15 @@
# 32/64
#.set BIOS_32,1

# this is for xlate setup of 2nd entry; it should be related to _fdata i think
# this is for i/d xlate setup of 2nd entry; it should be related to _fdata i think
.set BIOS_START,0x10000
# this is for d xlate setup of 3rd entry; it needs to be defined by memory map; it could be done by bios code,
# but has to be done before uart_init is called
.set CSR_START,0xFFF00000

# needed for litex
.set ROM_INIT,1

# not needed for litex
.set BIOS_STACK_0,_fstack-8
.set BIOS_STACK_1,_fstack-8
@ -81,6 +88,9 @@ _start:
int_000:
b boot_start

# ints need to handle save/restore and call to isr (like uart_isr())
# enable in a2node when it's safe (stack set up, etc.)

# critical input
.org 0x020
int_020:
@ -233,9 +243,6 @@ int_340:

# ------------------------------------------------------------------------------------------------------------------------------
# initial translation
# both erats:
# 00000000 64K: (rom, BE)
# 00010000 64K: (ram, BE or LE)
#
.org 0x400
boot_start:
@ -271,6 +278,18 @@ boot_start:
eratwe r8,r0,0
isync

# derat 29 @<CSR_START> I=1!!!
li r0,0x001D # entry #29
ori r10,r10,0x0F00 # word 2 with WIMG=F
load32 r4,CSR_START # word 1 rpn(32:51)=32:51 rpn(22:31)=54:63
load32 r8,CSR_START
ori r8,r8,0x023F # word 0 epn=32:51 class=52:53 v=54 x=55 size=56:59 thrd=60:63 size: 0001=4K 0011=64K 0101=1M 0111=16M 1010=1G

eratwe r10,r0,2
eratwe r4,r0,1
eratwe r8,r0,0
isync

lis r3,0x8800 # 32=ecl 36:37=tlbsel (10=i, 11=d)

# ierat 15 @00000000
@ -307,6 +326,49 @@ boot_start:

init_t0:

.ifdef ROM_INIT
########################################################################################################################################
# VMA/LMA: copy .data, clear .bss
rominit:
lis r1,_fdata_rom@h
ori r1,r1,_fdata_rom@l
lis r2,_fdata@h
ori r2,r2,_fdata@l
lis r3,_edata_rom@h
ori r3,r3,_edata_rom@l
lis r4,_fbss@h
ori r4,r4,_fbss@l
lis r5,_ebss@h
ori r5,r5,_ebss@l

subf r9,r1,r3
srwi. r9,r9,2
beq romcopy_done
mtctr r9
addi r1,r1,-4
addi r2,r2,-4

romcopy:
lwzu r9,4(r1)
stwu r9,4(r2)
bdnz romcopy

romcopy_done:
subf r9,r4,r5
srwi. r9,r9,2
beq romclear_done

mtctr r9
addi r4,r4,-4
li r9,0

romclear:
stwu r9,4(r4)
bdnz romclear

romclear_done:
.endif

# set up threads
# set thread configuration


@ -1,6 +1,27 @@
#ifndef __IRQ_H
#define __IRQ_H

// what do i implement for this?
// what if i want uart polling? uart still gen's uart_irq
// assign uart_irq = ((uart_pending_status[0] & uart_enable_storage[0]) | (uart_pending_status[1] & uart_enable_storage[1]));
// i have to disable in node i guess
/* uwatt
static inline void irq_setmask(unsigned int mask)
{
int irq;

// Enable all interrupts at a fixed priority level for now
int priority_level = PPC_EXT_INTERRUPT_PRIO;

// Iterate over IRQs configured in mask, and enable / mask in ICS
for (irq = 0; irq < PPC_XICS_SRC_NUM; irq++) {
if ((mask >> irq) & 0x1)
xics_ics_write_xive(irq, priority_level);
else
xics_ics_write_xive(irq, 0xff);
}
}
*/
static inline void irq_setmask(unsigned int mask) {
}


@ -1,61 +1,21 @@
// a2p

#ifndef __SYSTEM_H
#define __SYSTEM_H

#include <stdint.h>

/*
void flush_l2_cache(void) {
}
*/
static void flush_cpu_icache(void);
static void flush_cpu_dcache(void);

static void flush_cpu_icache(void) {
}
static void flush_cpu_dcache(void) {
}

#define CSR_ACCESSORS_DEFINED

#ifdef __ASSEMBLER__
#define MMPTR(x) x
#else /* ! __ASSEMBLER__ */

/* CSRs are stored in subregister slices of CONFIG_CSR_DATA_WIDTH (native
* endianness), with the least significant slice at the lowest aligned
* (base) address. */

#include <generated/soc.h>
#if !defined(CONFIG_CSR_DATA_WIDTH)
#error CSR_DATA_WIDTH MUST be set before including this file!
#ifdef __cplusplus
extern "C" {
#endif

/* CSR subregisters (a.k.a. "simple CSRs") are embedded inside uint32_t
* aligned locations: */
#define MMPTR(a) (*((volatile uint32_t *)(a)))

static inline unsigned long swizzle(unsigned long v);

static inline unsigned long swizzle(unsigned long v) {
return ((v & 0x000000FF) << 24) | ((v & 0x0000FF00) << 8) | ((v & 0x00FF0000) >> 8) | ((v & 0xFF000000) >> 24);
//return v;
static inline void flush_cpu_icache(void) {
}
static inline void flush_cpu_dcache(void){
};
void flush_l2_cache(void);

static inline void csr_write_simple(unsigned long v, unsigned long a)
{
//MMPTR(a) = v;
MMPTR(a) = swizzle(v);
}
void busy_wait(unsigned int ms);
void busy_wait_us(unsigned int us);

static inline unsigned long csr_read_simple(unsigned long a)
{
//return MMPTR(a);
return swizzle(MMPTR(a));
#ifdef __cplusplus
}

#endif /* ! __ASSEMBLER__ */
#endif

#endif /* __SYSTEM_H */


@ -101,6 +101,10 @@ class BaseSoC(SoCCore):

# no irq yet, but should be able to connect; need irq handler in crt0.s
self.add_constant('UART_POLLING')
# skip bios crc for sim
#self.add_constant('CONFIG_BIOS_NO_CRC') # doesnt work?
#self.add_config("BIOS_NO_CRC") # doesnt work?
#had to -DCONFIG_BIOS_NO_CRC=1 in GCC_FLAGS

# this appears to be how to set up fixed csr order but not sure it works this way. https://github.com/litex-hub/linux-on-litex-vexriscv/blob/master/soc_linux.py
#SoCCore.csr_map

File diff suppressed because it is too large Load Diff

@ -29,6 +29,14 @@
#include "Vsoc_iuq.h"
#include "Vsoc_iuq_cpl_top.h"
#include "Vsoc_iuq_cpl.h"
#include "Vsoc_iuq_slice_top.h"
#include "Vsoc_iuq_slice.h"
#include "Vsoc_iuq_rn_top.h"
#include "Vsoc_iuq_rn.h"
#include "Vsoc_iuq_rn_map__A24.h"
#include "Vsoc_xu.h"
#include "Vsoc_xu_gpr.h"
#include "Vsoc_tri_144x78_2r4w.h"

#ifdef TRACING
#include "verilated_vcd_c.h"
@ -37,9 +45,14 @@ VerilatedVcdC *t;
unsigned int t = 0;
#endif

/*
#include "uart/uartsim.h"
*/
// using https://github.com/ZipCPU/wbuart32 sim driver
// how does cpp get compiled in without this? can verilator be told to add more cpp? see a2p!
// UART=port
// 0xA20 = 2592
#ifdef UART
#include "wbuart32/bench/cpp/uartsim.h"
#include "wbuart32/bench/cpp/uartsim.cpp"
#endif

Vsoc* m;
#ifdef OLD_PUBLIC
@ -57,7 +70,7 @@ double sc_time_stamp() { // $time in verilog
const char* tbName = "tb_litex_soc";
const int resetCycle = 10;
const int threadRunCycle = resetCycle + 5;
const int runCycles = 100000;
const int runCycles = 100000000;
const int hbCycles = 500;
const int quiesceCycles = 50;
const int threads = 1;
@ -65,10 +78,11 @@ const std::string testFile = "";
const unsigned int bootAdr = 0x00000000;
const bool failMaxCycles = true;
const unsigned int stopOnHang = 500;
const unsigned int stopOnLoop = 10;
const unsigned int stopOnLoop = 20;
const unsigned long iarPass = 0x7F0;
const unsigned long iarFail = 0x7F4;
const bool debugWB = false;
const bool debugWB = true;
const bool debugWBReq = false;

// Cythonize this and use it for cocotb too...

@ -153,7 +167,6 @@ void Memory::write(unsigned int adr, unsigned int be, unsigned int dat) {
" " <<std::setw(8) << std::setfill('0') << std::uppercase << std::hex << startDat <<
"->" <<std::setw(8) << std::setfill('0') << std::uppercase << std::hex << this->read(adr) << std::endl;
}

}

Memory mem;
@ -179,6 +192,7 @@ int main(int argc, char **argv) {
cout << "Tracing enabled." << endl;
#endif

int i;
bool ok = true;
bool done = false;
bool resetDone = false;
@ -201,6 +215,22 @@ int main(int argc, char **argv) {
unsigned int iu0Comp, iu1Comp, iu0CompLast, iu1CompLast;
unsigned long iu0CompIFAR, iu1CompIFAR, iu0CompIFARLast, iu1CompIFARLast, iuCompFlushIFAR;

unsigned long gprCompMap[36], lastGprCompMap[36];
unsigned int vHi, vLo;
VlWide<3> gpr[144];


/*
# renamables
for i in range(36):
good, arch = sim.safeint(gprCompMap[i].value.binstr, 2, rc=True)
if good and arch != lastGprCompMap[i]:
sim.msg(f'C0: GPR Update: R{i:02d}={hex(gpr[arch], 16)}')
lastGprCompMap[i] = arch
*/
for (i = 0; i < 36; i++) {
lastGprCompMap[i] = i;
}

/*
# GPR pool and arch map
@ -261,9 +291,71 @@ int main(int argc, char **argv) {

*/

// memory setup
//mem.write(0xFFFFFFFC, 0x48000002);
//mem.loadFile(testFile);

// uart setup
/*
// i_setup[30] True if we are not using hardware flow control. This bit
// is ignored within this module, as any receive hardware flow
// control will need to be implemented elsewhere.
//
// i_setup[29:28] Indicates the number of data bits per word. This will
// either be 2'b00 for an 8-bit word, 2'b01 for a 7-bit word, 2'b10
// for a six bit word, or 2'b11 for a five bit word.
//
// i_setup[27] Indicates whether or not to use one or two stop bits.
// Set this to one to expect two stop bits, zero for one.
//
// i_setup[26] Indicates whether or not a parity bit exists. Set this
// to 1'b1 to include parity.
//
// i_setup[25] Indicates whether or not the parity bit is fixed. Set
// to 1'b1 to include a fixed bit of parity, 1'b0 to allow the
// parity to be set based upon data. (Both assume the parity
// enable value is set.)
//
// i_setup[24] This bit is ignored if parity is not used. Otherwise,
// in the case of a fixed parity bit, this bit indicates whether
// mark (1'b1) or space (1'b0) parity is used. Likewise if the
// parity is not fixed, a 1'b1 selects even parity, and 1'b0
// selects odd.
//
// i_setup[23:0] Indicates the speed of the UART in terms of clocks.
// So, for example, if you have a 200 MHz clock and wish to
// run your UART at 9600 baud, you would take 200 MHz and divide
// by 9600 to set this value to 24'd20834. Likewise if you wished
// to run this serial port at 115200 baud from a 200 MHz clock,
// you would set the value to 24'd1736
*/
/*
m_baud_counts = (isetup & 0x0ffffff);
m_nbits = 8-((isetup >> 28)&0x03);
m_nstop =((isetup >> 27)&1)+1;
m_nparity = (isetup >> 26)&1;
m_fixdp = (isetup >> 25)&1;
m_evenp = (isetup >> 24)&1;
*/

// 100MHz, 115200 = 868
#ifdef UART
UARTSIM *uart;
int uartPort = UART; // 0-stdin/stdout
//unsigned uartConfig = 1736;
unsigned uartConfig = 868;
//unsigned uartConfig = 434;
//unsigned uartConfig = 217;
//unsigned uartConfig = 217;

cout << "Initializing UART on port " << uartPort << " with config=" << hex << setw(8) << setfill('0') << uartConfig << endl;
uart = new UARTSIM(uartPort);
uart->setup(uartConfig);
#endif


// do something

root->soc->soc_rst = 1;

cout << dec << setw(8) << cycle << " Resetting..." << endl;
@ -298,6 +390,32 @@ int main(int argc, char **argv) {
if ((tick % ticks1x) == 0) {

// core

// completion

// gpr change
for (i = 0; i < 36; i++) {
gprCompMap[i] = root->soc->a2owb->c0->iuq0->iuq_slice_top0->slice0->rn_top0->fx_rn0->gpr_rn_map->comp_map_l2[i];
if (gprCompMap[i] != lastGprCompMap[i]) {
// need to left shift by 18 unused (96-78)!
vHi = root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][2] << 18;
vHi |= root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][1] >> 14;
vLo = root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][1] << 18;
vLo |= root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][0] >> 14;
cout << dec << setw(8) << setfill('0') << cycle << " C0: GPR Update: R";
cout << dec << setw(2) << setfill('0') << i << "=";
//cout << hex << setw(8) << setfill('0') << uppercase << root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][0] << " ";
//cout << hex << setw(8) << setfill('0') << uppercase << root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][1] << " ";
//cout << hex << setw(8) << setfill('0') << uppercase << root->soc->a2owb->c0->xu0->gpr->gpr0->mem[gprCompMap[i]][2] << " ";
cout << hex << setw(8) << setfill('0') << uppercase << vHi << "";
cout << hex << setw(8) << setfill('0') << uppercase << vLo << " ";
cout << "[" << dec << setw(3) << setfill('0') << gprCompMap[i] << "]";
cout << endl;
lastGprCompMap[i] = gprCompMap[i];
}
}

// completions
iu0Comp = root->soc->a2owb->c0->iuq0->iuq_cpl_top0->iuq_cpl0->cp2_i0_completed;
iu1Comp = root->soc->a2owb->c0->iuq0->iuq_cpl_top0->iuq_cpl0->cp2_i1_completed;
iu0CompIFAR = root->soc->a2owb->c0->iuq0->iuq_cpl_top0->iuq_cpl0->cp2_i0_ifar << 2;
@ -324,11 +442,13 @@ int main(int argc, char **argv) {
quiesceCount = 5;
} else if ((iu0Comp == iu0CompLast) && (!iu0Comp || (iu0CompIFAR == iu0CompIFARLast)) &&
(iu1Comp == iu1CompLast) && (!iu1Comp || (iu1CompIFAR == iu1CompIFARLast))) {
lastCompSame++;
if (stopOnLoop && (lastCompSame == stopOnLoop)) {
ok = false;
cout << "*** Loop detected for " << dec << stopOnLoop << " iterations ***" << endl;
}
if (!iu0Comp || !iu1Comp) { // don't count if both are valid (assume only 1-op loops are bad)
lastCompSame++;
if (stopOnLoop && (lastCompSame == stopOnLoop)) {
ok = false;
cout << "*** Loop detected for " << dec << stopOnLoop << " iterations ***" << endl;
}
}
} else {
iu0CompLast = iu0Comp;
iu0CompIFARLast = iu0CompIFAR;
@ -360,11 +480,11 @@ int main(int argc, char **argv) {

} else if (root->soc->a2owb->wb_cyc && root->soc->a2owb->wb_stb) {
if (!root->soc->a2owb->wb_we) {
if (debugWB)
if (!wbRdPending && debugWBReq)
cout << dec << setw(8) << setfill('0') << uppercase << cycle << " WB RD RA=" << setw(8) << hex << setfill('0') << root->soc->a2owb->wb_adr << endl;
wbRdPending = true;
} else {
if (debugWB)
if (!wbWrPending && debugWBReq)
cout << dec << setw(8) << setfill('0') << uppercase << cycle << " WB WR RA=" << setw(8) << hex << setfill('0') << root->soc->a2owb->wb_adr <<
" SEL=" << root->soc->a2owb->wb_sel << " DATA=" << setw(8) << hex << setfill('0') << root->soc->a2owb->wb_datw << endl;
wbWrPending = true;
@ -373,7 +493,13 @@ int main(int argc, char **argv) {

// leds, btns, mem, etc.

// uart
} else {

if (resetDone) {
#ifdef UART
m->serial_rx = (*uart)(m->serial_tx);
#endif
}

}


@ -0,0 +1 @@
/home/wtf/projects/wbuart32

@ -8,6 +8,40 @@
* runs simple version of kernel/bios/random test with cocotb (A2L2 interface partially implemented in Python) and Verilog core wrappers (A2L2<->mem/wb interfaces)
* wrapper converts A2L2 interface to mem and Wishbone interfaces
* verilator now runs with a2o_litex and litex SOC
* verilator & litex software build working for 32BE but looks like problem with printf %d

```
litex_term socket://localhost:2592

__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!

(c) Copyright 2012-2022 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs

BIOS built on Aug 21 2022 18:36:00

LiteX git sha1: 33ae301d

--=============== SoC ==================--
CPU: a2owb @ 10<31>MHz
BUS: WISHBONE 39-bit @ 4GiB
CSR: 39-bit data
ROM: 6<>KiB
SRAM: 6<>KiB
MAIN-RAM: 16<31><36>{KiB

--========== Initialization ============--

--============= Console ================--

litex> wtf
Command not found
litex>
```

## To Do


Loading…
Cancel
Save